App Router とは何か。Pages Router との違い
App Router は、app フォルダの中のフォルダ名でパスが決まり、page という名前のファイルだけが画面になる、Next.js のいまの標準のルーターです。
フォルダがパス、page が中身
App Router のルーティングには設定ファイルがありません。フォルダを作った場所がそのまま URL になります。
app/page.tsx → /
app/about/page.tsx → /about
app/blog/[slug]/page.tsx → /blog/なんでも
ここで大事なのは、フォルダとファイルが別々の役割を持っていることです。
| 決めるもの | 担当 | 例 |
|---|---|---|
| URL のどこか | フォルダ名 | app/about |
| そこに画面があるか | page という名前 | page.tsx |
だから app/about/ というフォルダがあっても、中に page.tsx が無ければ /about は存在しません。フォルダは部品や型の置き場としても使えます。
page のほかに決まった名前がある
フォルダの中で特別な意味を持つファイル名は、page だけではありません。どれも、置いたフォルダから下に効きます。
| ファイル | 役割 | 詳しく |
|---|---|---|
| page.tsx | その URL の画面 | このページ |
| layout.tsx | 下のページを包む共通の枠。CSS もここで読み込む | CSS が反映されないとき |
| loading.tsx | 読み込み中に先に出す画面 | 読み込み中の最小構成 |
| error.tsx | 例外を受け止める画面。use client が要る | エラー画面の作り方 |
| not-found.tsx | 見つからないときの画面 | not-found.tsx が効かないとき |
| route.ts | 画面ではなく、好きな応答を返す口 | このページの下のほう |
置いただけでは、ページにならない
ここがいちばん怖いところです。名前を間違えても、エラーが1つも出ません。
実機で確かめました。app/about/index.tsx を置いてビルドすると、こうなります。
Route (app)
┌ ○ /
└ ○ /_not-found
/about がありません。それでもビルドは成功します。警告も出ません。そのままデプロイが通り、開いて初めて 404 に気づきます。
Pages Router と何が違うか
| こと | Pages Router | App Router |
|---|---|---|
| 画面のファイル名 | そのファイル自体 | page という名前だけ |
| 既定の実行場所 | ブラウザにも送られる | サーバーだけ |
| データの取り方 | getServerSideProps など | コンポーネントの中で await |
| 共通の枠 | _app.tsx が1つ | layout.tsx を階層ごとに |
| API の置き場 | pages/api | route という名前 |
いちばん大きい違いは2行目です。App Router では、書いたコンポーネントは既定で Server Component です。ブラウザの機能が要るところにだけ use client を書いて、境界を引きます。ここがこのサイトの本題で、Server Component とは何かから順に扱っています。
同じパスを2つが持つことはできない
App Router と Pages Router は同じプロジェクトに共存できます。移行の途中はその状態になります。
ただし、同じパスを両方が持つことはできません。実機で確かめた文言です。
Error: App Router and Pages Router both match path: /about
Next.js does not support having both App Router and Pages Router routes
matching the same path. Please remove one of the conflicting routes.
優先順位は作られません。どちらかを消すまでビルドが止まります。
括弧で囲んだフォルダは、パスに出ない
フォルダ名を丸括弧で囲むと、URL には現れません。まとめたいだけのときに使います。
app/(marketing)/about/page.tsx → /about
app/(marketing)/layout.tsx → /about に共通の枠が付く
実機で確かめました。このとき出来たルートは /about で、marketing は入りません。
便利ですが、URL に出ないということは、衝突にも気づきにくいということです。別々の括弧の中に同じパスを作ると、こうなります。
Error: You cannot have two parallel pages that resolve to the same path.
Please check /(docs)/about and /(marketing).
画面と API を同じパスに置けない
page は HTML を返す口、route は好きな応答を返す口です。同じフォルダに両方置くと止まります。
app/about/page.tsx app/about/route.ts
Conflicting route and page at /about
app/about/page.tsx app/api/about/route.ts
同じデータを使いたいなら、共通の関数を作って両方から呼ぶ。
ブラウザが画面を要求するときも GET なので、「GET は route、画面は page」という分担は成り立ちません。だから分けるしかありません。
動くものを見る
このサイトには、実際に動いているページのファイルをそのまま出している最小構成があります。App Router のフォルダがどう並ぶかは、説明より実物のほうが早いです。
- 一覧と詳細の最小構成 — フォルダとファイルが URL になるところ
- 404 とエラーの最小構成 —
not-found.tsxなどの決まった名前
どちらを使うか
新しく作るなら App Router です。Pages Router がすぐ消えるわけではありませんが、新しい機能は App Router 側に入ります。
既にある Pages Router のアプリは、全部を一度に移す必要はありません。共存できるので、パス単位で少しずつ動かせます。止まるのは同じパスが重なったときだけです。
出典
- nextjs.org/docs/app/getting-started/project-structure
- nextjs.org/docs/app/api-reference/file-conventions/page
- nextjs.org/docs/app/guides/migrating/app-router-migration
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。