なぜこの記事を書こうと思ったのか。
Reactの実装経験一年半を経て、今後のスキルアップのためにNext.jsの学習を始めました。
Udemyのハンズオン教材 -> 自作アプリの作成 -> 再度Udemyの開設講座の受講中。
Reactの基礎知識があれば習得難易度が高くないとのことだったのですが、AppRouterの考え方などからReact実装時と割とことなる考え方があったりと、なかなか最初見ていて理解に苦しんだところもあったので、忘備録的な意味合いも兼ねてアウトプットしてみたいと思います。
AppRouterのディレクトリ構成について
基本的に、Appディレクトリ下にはcomponentsなどのファイル配置は行わない方がよいみたい。
確実にとも言い難いところなのと、現場依存になってしまうところもあるが、Appディレクトリの下は「ルーティング」に関することだけを書くのがベター。
ただし、後述するAppRouter独自のファイル名称のもの(error.tsxやloading.tsx)は、必ずappディレクトリ下に配置する必要がある。(こちらに関してはapp下でなくては機能しなくなってしまうため。)
AppRouterによるNext.js独自のファイル名称がある
個人的にReactを開発する際はアトミックデザイン採用をしており、独自の考え方でコンポーネントの切り分け方を見直すなどしていました。
コンポーネントディレクトリ内部にindex.tsxとしてルートファイルを配置、といった具合です。
この考え方に固着していた点もあり、そもそもNextJsにおけるAppRouterの考え方につまづいていました。
Approuter - Next.jsの独自のファイル名称一覧
ファイル名称 | ファイルの役割 | 備考 |
---|---|---|
page.tsx | ルーディングとして認識されるページファイル | app/ 配下に配置すると、自動的に URL に対応するルートになる (app/home/page.tsx → /home) |
layout.tsx | page.tsx をラップする共通レイアウト | children を受け取り、ヘッダーやフッターなどを適用できる |
loading.tsx | ページ取得中に表示されるローディング UI | SSR or CSR どちらでも利用可能 (loading.tsx は useEffect + axios.get()などには反応しない) |
not-found.tsx | URLで無効なパスを指定した際に表示されるnot-foundページ | next/navigation の notFound() を呼び出して手動で遷移させることも可能 |
error.tsx | キャッチされないエラー (throw new Error()) が発生した際に表示される | try/catch でキャッチした場合は適用されない。また、サーバー自体が落ちたなどのケースでは、Next.Js自体が動作しないのでerror.tsxも出力されない。 |
route.ts | API ルート (/api/ 配下) を作成する | GET, POST, DELETE などの HTTP メソッドごとに関数を定義する |
src/
├── app/
│ ├── layout.tsx
│ ├── page.tsx
│ ├── error.tsx ✅ ← ここに配置!
│ ├── dashboard/
│ │ ├── page.tsx
│ │ ├── error.tsx ✅ ← 各ページごとに配置も可能!
│ └── settings/
│ ├── page.tsx
│ ├── error.tsx ✅ ← ここでもOK!
├── components/ ❌ `error.tsx` は置けない
├── utils/ ❌ `error.tsx` は置けない
└── styles/
Approuter - Next.js の特殊なディレクトリ構造
ディレクトリ名 | 意味 | URLへの影響 | 例 | 生成されるルート |
---|---|---|---|---|
(グループ名)/ | URL に影響しないグループ化 | 影響なし | app/(dashboard)/users/page.tsx | /users |
[id]/ | 動的ルーティング(パスパラメータ) | 影響あり | app/users/[id]/page.tsx | /users/:id |
ディレクトリ構成とファイル名称のまとめ
src/
├── app/
│ ├── (dashboard)/ ← ✅ グルーピング(URLには影響しない)
│ │ ├── layout.tsx ← Dashboard 全体のレイアウト
│ │ ├── users/
│ │ │ ├── page.tsx ← `/users` に対応
│ │ │ ├── [id]/ ← ✅ 動的ルーティング(URLに影響する)
│ │ │ │ ├── page.tsx ← `/users/:id` に対応
│ │ │ │ ├── settings/
│ │ │ │ │ ├── page.tsx ← `/users/:id/settings`
│ │ │ │ │ ├── error.tsx ← `/users/:id/settings` でエラー発生時に表示
│ │ │ │ │ ├── loading.tsx ← `/users/:id/settings` のロード中に表示
│ │ │ │ ├── layout.tsx ← `/users/:id` 以下の共通レイアウト
│ │ ├── reports/
│ │ │ ├── page.tsx ← `/reports` に対応
│ │ │ ├── [[...filters]]/ ← ✅ オプショナルキャッチオール(パスなしもOK)
│ │ │ │ ├── page.tsx ← `/reports` または `/reports/foo/bar`
│ │ │ ├── layout.tsx ← `/reports` の共通レイアウト
│ ├── settings/
│ │ ├── page.tsx ← `/settings` に対応
│ │ ├── layout.tsx ← `/settings` 以下の共通レイアウト
│ │ ├── profile/
│ │ │ ├── page.tsx ← `/settings/profile` に対応
│ │ │ ├── edit/
│ │ │ │ ├── page.tsx ← `/settings/profile/edit` に対応
│ ├── api/
│ │ ├── user/
│ │ │ ├── route.ts ← `/api/user` に対応(APIエンドポイント)
│ │ ├── reports/
│ │ │ ├── [id]/route.ts ← `/api/reports/:id` に対応(動的API)
│ ├── layout.tsx ← アプリ全体のレイアウト
│ ├── error.tsx ← アプリ全体のエラーページ
│ ├── loading.tsx ← グローバルなローディングUI
│ ├── not-found.tsx ← 404ページ
│ ├── page.tsx ← `/` に対応(トップページ)
│
│
├── (components, hooks, utils等)
最後に
引き続き学習しながらこの記事は更新していきたいと思います。ありがとうございました。