Next.jsのファイルベースルーティング入門 — フォルダ構成でURLが決まる仕組み
はじめに
Next.jsの特徴の一つが「ファイルベースルーティング」です。
通常のReactアプリでは react-router-dom などでルーティングを自分で定義しますが、Next.jsではフォルダとファイルを作るだけでURLが自動的に決まります。
App Router の基本構造
Next.js 13以降の App Router では、app/ ディレクトリの構成がそのままURLになります。
app/
├── page.tsx → /
├── about/
│ └── page.tsx → /about
├── blog/
│ ├── page.tsx → /blog
│ └── [id]/
│ └── page.tsx → /blog/123、/blog/456 など
└── dashboard/
├── layout.tsx
└── page.tsx → /dashboard
ルールはシンプルです。
-
page.tsxが置かれたフォルダがURLになる -
[id]のように角括弧で囲むと動的ルート(パラメータ)になる
page.tsx の基本
// app/about/page.tsx → /about にアクセスした時に表示される
export default function AboutPage() {
return (
<main>
<h1>Aboutページ</h1>
</main>
);
}
export default でコンポーネントをエクスポートするだけです。
動的ルート(Dynamic Routes)
[id] のようにフォルダ名を角括弧で囲むと、URLのその部分が動的パラメータになります。
app/blog/[id]/page.tsx → /blog/1、/blog/hello など
// app/blog/[id]/page.tsx
type Props = {
params: { id: string };
};
export default function BlogPost({ params }: Props) {
return <h1>記事ID: {params.id}</h1>;
}
/blog/123 にアクセスすると params.id が "123" になります。
複数パラメータ
app/shop/[category]/[id]/page.tsx → /shop/books/42
type Props = {
params: { category: string; id: string };
};
キャッチオールルート
app/docs/[...slug]/page.tsx → /docs/a/b/c など階層を全てキャッチ
layout.tsx — 共通レイアウト
layout.tsx を置くと、そのフォルダ以下のページに共通のレイアウトを適用できます。
// app/layout.tsx(全ページ共通)
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>
<header>共通ヘッダー</header>
{children}
<footer>共通フッター</footer>
</body>
</html>
);
}
// app/dashboard/layout.tsx(dashboardだけの共通レイアウト)
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<nav>サイドバー</nav>
<main>{children}</main>
</div>
);
}
レイアウトはネストできます。app/layout.tsx → app/dashboard/layout.tsx → app/dashboard/page.tsx の順で入れ子になります。
特殊なファイル一覧
| ファイル名 | 役割 |
|---|---|
page.tsx |
ページ本体 |
layout.tsx |
共通レイアウト |
loading.tsx |
ローディング中に表示するUI |
error.tsx |
エラー時に表示するUI |
not-found.tsx |
404ページ |
リンクの書き方
Next.jsでは <a> タグではなく <Link> コンポーネントを使います。
import Link from 'next/link';
export default function Nav() {
return (
<nav>
<Link href="/">ホーム</Link>
<Link href="/about">About</Link>
<Link href="/blog/123">記事123</Link>
</nav>
);
}
<a> タグだとページ全体がリロードされますが、<Link> を使うとクライアントサイドでの画面遷移(高速)になります。
プログラムでのページ遷移
'use client';
import { useRouter } from 'next/navigation';
export default function BackButton() {
const router = useRouter();
return (
<button onClick={() => router.push('/dashboard')}>
ダッシュボードへ
</button>
);
}
useRouter はClient Componentでのみ使えます(先頭に 'use client' が必要)。
まとめ
| 概念 | ひとこと |
|---|---|
| ファイルベースルーティング | フォルダ構成 = URL構成 |
page.tsx |
そのURLのページ本体 |
layout.tsx |
配下ページ共通のレイアウト |
[id] フォルダ |
動的パラメータ(URLの一部を変数に) |
<Link> |
ページ遷移はaタグではなくLinkを使う |
設定ファイルでルーティングを定義する方式に慣れているとNext.jsの「フォルダ=URL」という発想は新鮮ですが、慣れると直感的でとても扱いやすいです。
次回はSSR/SSG/ISRの違いとデータ取得戦略を整理します。