レイアウトとページの作成方法
Next.jsはファイルシステムベースのルーティングを使用しており、フォルダとファイルを使ってルートを定義できます。このページでは、レイアウトとページを作成し、それらの間をリンクする方法を説明します。
ページの作成
ページとは特定のルートでレンダリングされるUIです。ページを作成するには、app
ディレクトリ内にpage
ファイルを追加し、Reactコンポーネントをデフォルトエクスポートします。例えば、インデックスページ(/
)を作成する場合:

export default function Page() {
return <h1>Hello Next.js!</h1>
}
export default function Page() {
return <h1>Hello Next.js!</h1>
}
レイアウトの作成
レイアウトとは複数のページ間で共有されるUIです。ナビゲーション時、レイアウトは状態を保持し、インタラクティブなまま再レンダリングされません。
layout
ファイルからReactコンポーネントをデフォルトエクスポートすることでレイアウトを定義できます。このコンポーネントは、ページまたは別のレイアウトとなるchildren
プロップを受け取る必要があります。
例えば、インデックスページを子として受け取るレイアウトを作成するには、app
ディレクトリ内にlayout
ファイルを追加します:

export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{/* レイアウトUI */}
{/* ページまたはネストされたレイアウトをレンダリングしたい場所にchildrenを配置 */}
<main>{children}</main>
</body>
</html>
)
}
export default function DashboardLayout({ children }) {
return (
<html lang="en">
<body>
{/* レイアウトUI */}
{/* ページまたはネストされたレイアウトをレンダリングしたい場所にchildrenを配置 */}
<main>{children}</main>
</body>
</html>
)
}
上記のレイアウトはルートレイアウトと呼ばれ、app
ディレクトリのルートで定義されています。ルートレイアウトは必須で、html
タグとbody
タグを含む必要があります。
ネストされたルートの作成
ネストされたルートとは、複数のURLセグメントで構成されるルートです。例えば、/blog/[slug]
ルートは3つのセグメントで構成されます:
/
(ルートセグメント)blog
(セグメント)[slug]
(リーフセグメント)
Next.jsでは:
- フォルダはURLセグメントにマッピングされるルートセグメントを定義するために使用されます。
- ファイル(
page
やlayout
など)はセグメントに対して表示されるUIを作成するために使用されます。
ネストされたルートを作成するには、フォルダを互いに入れ子にします。例えば、/blog
のルートを追加するには、app
ディレクトリ内にblog
というフォルダを作成します。次に、/blog
を公開可能にするために、page.tsx
ファイルを追加します:

// ダミーインポート
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
// ダミーインポート
import { getPosts } from '@/lib/posts'
import { Post } from '@/ui/post'
export default async function Page() {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</ul>
)
}
フォルダのネストを続けることで、ネストされたルートを作成できます。例えば、特定のブログ投稿のルートを作成するには、blog
内に新しい[slug]
フォルダを作成し、page
ファイルを追加します:

function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
function generateStaticParams() {}
export default function Page() {
return <h1>Hello, Blog Post Page!</h1>
}
フォルダ名を角括弧で囲む(例:[slug]
)ことで、データから複数のページを生成するダイナミックルートセグメントを作成できます。例:ブログ投稿、商品ページなど。
レイアウトのネスト
デフォルトでは、フォルダ階層内のレイアウトもネストされており、children
プロップを介して子レイアウトをラップします。特定のルートセグメント(フォルダ)内にlayout
を追加することでレイアウトをネストできます。
例えば、/blog
ルートのレイアウトを作成するには、blog
フォルダ内に新しいlayout
ファイルを追加します。

export default function BlogLayout({
children,
}: {
children: React.ReactNode
}) {
return <section>{children}</section>
}
export default function BlogLayout({ children }) {
return <section>{children}</section>
}
上記の2つのレイアウトを組み合わせると、ルートレイアウト(app/layout.js
)がブログレイアウト(app/blog/layout.js
)をラップし、ブログレイアウトがブログ(app/blog/page.js
)とブログ投稿ページ(app/blog/[slug]/page.js
)をラップします。
ダイナミックセグメントの作成
ダイナミックセグメントを使用すると、データから生成されるルートを作成できます。例えば、個々のブログ投稿ごとに手動でルートを作成する代わりに、ブログ投稿データに基づいてルートを生成するダイナミックセグメントを作成できます。
ダイナミックセグメントを作成するには、セグメント(フォルダ)名を角括弧で囲みます:[segmentName]
。例えば、app/blog/[slug]/page.tsx
ルートでは、[slug]
がダイナミックセグメントです。
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
const post = await getPost(slug)
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
)
}
export default async function BlogPostPage({ params }) {
const { slug } = await params
const post = await getPost(slug)
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
)
}
ダイナミックセグメントについて詳しく学びます。
ページ間のリンク作成
<Link>
コンポーネントを使用してルート間をナビゲートできます。<Link>
はNext.jsの組み込みコンポーネントで、HTMLの<a>
タグを拡張し、プリフェッチとクライアントサイドナビゲーションを提供します。
例えば、ブログ投稿のリストを生成するには、next/link
から<Link>
をインポートし、href
プロップをコンポーネントに渡します:
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
import Link from 'next/link'
export default async function Post({ post }) {
const posts = await getPosts()
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
豆知識:
<Link>
はNext.jsでルート間をナビゲートする主要な方法です。より高度なナビゲーションにはuseRouter
フックも使用できます。