Anker PowerLine III Flow USB-C & USB-C ケーブル Anker絡まないケーブル 100W 結束バンド付き USB PD対応 シリコン素材採用 iPhone 16 / 15 / Galaxy iPad Pro MacBook Pro/Air 各種対応 (1.8m ミッドナイトブラック)
¥1,890 (2025年4月25日 13:07 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
はじめに
先日、React の勉強会で、Next.js App Router の設定やファイル規約について取り上げました 🫐
App Router では、エラー・ローディング状態や、
SEO 設定の方法を簡略化してくれています!
今回は、Next.js App Router における特別ファイルの種類と使い方を調査したので、基礎的な内容をまとめました!
時間の節約になれば、嬉しいです 🙌
Next.js App Router の特別ファイルとは?
Next.js App Router の特別ファイルとは、特定の名前を持つファイルで、その名前に応じた特別な役割を果たします。
上記の公式を見るとわかりますが、
たくさんありますね、、🧐
これらのファイルでは、:
- ルーティング
- レイアウト
- メタデータ
- エラーハンドリングなど、、
Web アプリケーション開発に必要な、様々な機能を提供します!
Next.js App Router の特別ファイル・設定まとめ
それでは、主要な特別ファイル・設定について、
テンポよく紹介していきます 😎
layout.tsx(共通レイアウト)
layout
ファイルは、複数のページで共有される UI コンポーネントを定義します。
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
html lang="ja">
body>
header>共通ヘッダーheader>
{children}
footer>共通フッターfooter>
body>
html>
);
}
レイアウトは入れ子にすることができ、
親レイアウトの children
として子レイアウトや子ページが表示されます。
(Nested Layout)
ルートレイアウト(app/layout.js
)は必須で、html
タグと body
タグを含める必要があります!
page.tsx(ページファイル)
page
ファイルは、特定のルートの主要な UI コンポーネント(ページ)を定義します。
このファイルが存在するディレクトリは、公開されたルートとなります。
export default function AboutPage() {
return (
div>
h1>About Ush1>
p>会社についての情報です。p>
div>
);
}
この例では、/about
にアクセスすると、AboutPage コンポーネントが表示されます。
route.ts(API エンドポイントの構築)
route
ファイルは、API エンドポイントを定義します。
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
return NextResponse.json({ message: "Hello, world!" });
}
この例では、/api/hello
にアクセスすると、{ message: "Hello, world!" }
を JSON 形式で返します。
静的なページの metadata
page
ファイル、もしくは layout
ファイルに、metadata
オブジェクトをエクスポートすることで、静的なメタデータを定義できます。
import { Metadata } from "next";
export const metadata: Metadata = {
title: "商品一覧",
description: "当店で取り扱っている商品の一覧です",
};
export default function ProductsPage() {
return div>商品一覧ページdiv>;
}
動的なページの metadata
動的なページの場合、
ページの内容ごとにメタデータも変化することが想定されます!
その場合、generateMetadata
関数をエクスポートすることで、動的なメタデータを生成できます。
import { Metadata } from "next";
type Props = {
params: { id: string };
};
export async function generateMetadata({ params }: Props): PromiseMetadata> {
const product = await getProduct(params.id);
return {
title: product.name,
description: product.description,
};
}
export default async function ProductPage({ params }: Props) {
const product = await getProduct(params.id);
return div>{product.name}の詳細ページdiv>;
}
サイトマップ
sitemap.ts
ファイルを作成することで、サイトマップを生成できます。
import { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: "https://example.com",
lastModified: new Date(),
changeFrequency: "yearly",
priority: 1,
},
{
url: "https://example.com/about",
lastModified: new Date(),
changeFrequency: "monthly",
priority: 0.8,
},
{
url: "https://example.com/blog",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.5,
},
];
}
もし、サイトマップ自体について知りたい場合は、下記もチェックしてみてください:
このファイルにより、/sitemap.xml
エンドポイントが自動的に生成されます!
robots txt
robots.ts
ファイルで、検索エンジンのクローラー向けの指示を設定できます。
import { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "https://zenn.dev/",
disallow: "/private/",
},
sitemap: "https://example.com/sitemap.xml",
};
}
このファイルにより、/robots.txt
エンドポイントが自動的に生成されます。
JSON-LD (構造化データ)
JSON-LD は、検索エンジンがウェブページの内容を理解するのに役立つ構造化データです。
特別ファイルではありませんが、メタデータやコンポーネント内で定義することができます。
import { product } from "./data";
export default function Page({ params }) {
const productData = product(params.id);
const jsonLd = {
"@context": "https://schema.org",
"@type": "Product",
name: productData.name,
description: productData.description,
image: productData.image,
offers: {
"@type": "Offer",
price: productData.price,
priceCurrency: "JPY",
},
};
return (
>
script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
h1>{productData.name}h1>
{}
>
);
}
もし、JSON-LD 自体について知りたい場合は、下記もチェックしてみてください:
ローディング(読み込み中)のページ
loading
ファイルには、ページやレイアウトがロード中に表示される UI を定義します。
export default function Loading() {
return (
div className="loading-spinner">
p>データを読み込み中...p>
div>
);
}
このファイルは React の Suspense と組み合わせて使用され、
ページがデータをロードしている間にのみ、自動で表示されます。
エラーページ
error
ファイルは、ページやレイアウトでエラーが発生した場合に表示される UI を定義します。
"use client";
import { useEffect } from "react";
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
useEffect(() => {
console.error(error);
}, [error]);
return (
div>
h2>エラーが発生しましたh2>
button onClick={() => reset()}>再試行button>
div>
);
}
このファイルは 'use client'
ディレクティブが必須で、クライアントコンポーネントとして機能します。
存在しないページ(404 Not Found)
not-found
ファイルは、ページが見つからない場合(404 エラー)に表示される UI を定義します。
export default function NotFound() {
return (
div>
h2>ページが見つかりませんh2>
p>お探しのページは存在しないか、移動した可能性があります。p>
div>
);
}
静的な OGP 画像ファイル
TOP ページ用の OG 画像のように、静的に用意した画像の場合は、opengraph-image.png
などの画像ファイルを、app
直下に配置するだけで、自動で設定されます!
動的な OGP 画像の自動生成
ブログ記事のページなどの動的なページでは、opengraph-image.tsx
または twitter-image.tsx
ファイルを使って、動的な OGP 画像を生成できます!
import { ImageResponse } from "next/server";
export const runtime = "edge";
export const contentType = "image/png";
export const size = {
width: 1200,
height: 630,
};
export default async function Image({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
return new ImageResponse(
(
div
style={{
display: "flex",
color: "white",
background: "linear-gradient(to right, #0099F7, #F11712)",
width: "100%",
height: "100%",
padding: "50px",
textAlign: "center",
justifyContent: "center",
alignItems: "center",
}}
>
div style={{ fontSize: 60, fontWeight: "bold" }}>{post.title}div>
div>
),
{
...size,
}
);
}
opengraph-image.tsx
と twitter-image.tsx
を分ける必要がない場合は、opengraph-image.tsx
のみを配置しれば、両方に適用されますよ 👍
そして、もし、画像生成機能の ImageResponse
自体について知りたい場合は、
下記もチェックしてみてください:
アイコン系(favicon, apple-icon など)
サイトのロゴとなるアイコン系の画像も、app
直下に配置することで設定可能です:
apple-icon.png
favicon.ico
icon.svg
manifest.json
もし、それそれのアイコンの必要性について確認したい場合は、下記もチェックしてみてください:
おわりに
最後まで読んでいただき、ありがとうございます 🥳
下記の、React ハンズオン勉強会での、振り返りのような記事ですが、
少しでも参考になれば、嬉しいです!
そして、もし、間違いや補足情報などがありましたら、
ぜひコメントを追加してください!
Happy Hacking 🙂