9. parallel routes
Page ごとに Header を変更する
下記のように、Page ごとに Header を変更できるようにしてみましょう。
| inbox | draft | 
|---|---|
|  |  | 
今回は、parallel routes を利用して、Page ごとに Header を変更する方法を紹介します。
実装する
apps/workspace/app/(dashboard)/layout.tsx を下記のように変更します
// apps/workspace/app/(dashboard)/layout.tsxexport default function dashboardLayout(props: {  children: React.ReactNode;  header: React.ReactNode;}) {  return (    <main className="relative">      <div className="p-8 h-dvh">        <div className="flex items-center justify-between">          <h1 className="text-4xl font-extrabold tracking-tight">            The Joke Mail Service            {props.header}          </h1>          <form action={logout}>次に、apps/workspace/app/(dashboard)/@header/inbox/page.tsxを新規で作成します。
mkdir -p "apps/workspace/app/(dashboard)/@header/inbox"touch "apps/workspace/app/(dashboard)/@header/inbox/page.tsx"export default function Header() {  return "The Joke Mail Service | Inbox";}この時点で、http://localhost:3000/inbox にアクセスすると、Header が The Joke Mail Service | Inbox に変更されます。
つぎに、http://localhost:3000/drafts にアクセスしてみてください。404エラーが表示されると思います。
これは、@headers という形で分割された先にPageが存在しないためです。
draftも同様に追加してみましょう。
mkdir -p "apps/workspace/app/(dashboard)/@header/drafts"touch "apps/workspace/app/(dashboard)/@header/drafts/page.tsx"export default function Header() {  return "The Joke Mail Service | Drafts";}これで http://localhost:3000/drafts にアクセスしても、404が表示されなくなったと思います。
ここで「すべてのページに追加しなければならないのか?」と思うかもしれません。
実は、存在しないPageにアクセスした場合のために、default.tsx をつかって、デフォルトのHeaderを表示することができます。
実際にdefault.tsx を作成してみましょう。
touch "apps/workspace/app/(dashboard)/@header/default.tsx"export default function Header() {  return "The Joke Mail Service";}これで、http://localhost:3000/sentにアクセスした場合には、The Joke Mail Service が表示されるようになっていると思います。
parallel routes の仕様について理解する
ここで少し不思議な現象を確認してみましょう。
まず、http://localhost:3000/inbox にアクセスしてみてください。
その後、サイドバーから、`Sent` Button クリックして、http://localhost:3000/sent にアクセスしてみてください。
すると、Header が The Joke Mail Service | Inbox のまま変更されないことを確認できると思います。
また、その場でリロード(または、直接アクセス)すると、Header が The Joke Mail Service に変更されることを確認できると思います。
これは parallel routes の仕様です。
ソフトナビゲーション(Next Link)では、遷移先の URL と一致するサブページ(今回でいうと@header/sent/page.tsx)がなくても、現在のサブページを維持して遷移します。
ハードナビゲーション(ブラウザーのリロードや直接アクセスされた時) では、 URL と一致するサブページがない場合は、default.js が表示されます。default.js がない場合は、404 が表示されます。
「結局すべてのページに追加しなければならないのか?」と思うかもしれません。
catch-all route を使うことで解決することができます。
catch-all route は、[...catchAll]/page.tsx という形で指定することができます。どれにもマッチしない場合はこのページが表示されます。
これは、default.tsx よりも優先されます。
mkdir -p "apps/workspace/app/(dashboard)/@header/[...catchAll]"touch "apps/workspace/app/(dashboard)/@header/[...catchAll]/page.tsx"//apps/workspace/app/(dashboard)/@header/[...catchAll]/page.tsxexport default function Header() {  return "The Joke Mail Service";}これで、http://localhost:3000/sentにアクセスした場合には、The Joke Mail Service が表示されるようになっていると思います。
まとめ
今回は、parallel routes を利用して、Page を分割する方法を紹介しました。
parallel routes を利用することで、Layout をより柔軟に設計することができます。
Next.js 15 rc
Next.js 15 rc では、parallel routes でも chatch-all route の path params を引数として受け取ることができるようになりました。
cd apps/solution/pnpm install next@rc react@rc react-dom@rccd ../../pnpm dev//apps/solution/app/(dashboard)/@header/[...catchAll]/page.tsxexport default function Header(props: { params: { catchAll: string[] } }) {  return `The Joke Mail Service | ${props.params.catchAll.join(' | ')}`;}