App Routerではフォルダ名やファイル名に基づいてアプリケーションのナビゲーションなどの挙動を設定します。この記事ではそんなフォルダ名やファイル名についてパターンを一覧で見れるようにまとめました。
ファイル
ルーティングに関するファイル
page
マッピングされたページごとのUIを記述するファイルです。ページの主要な内容はここに記述されます。
layout
マッピングされたページとそれ以降のページに対するUIを記述するファイルです。
appは以下にある場合はhtmlタグやbodyタグを用いて記述する必要があり、App Routerでは配置することが必須となっています。
template
layoutに似たような動きをするファイルです。こちらのファイルはappに置くことは強制されていません。
layoutと大きく異なる部分はナビゲーション毎の動作です。templateではナビゲーション毎にUIを作り直すので状態が初期化されてしまいます。ページ毎になんらかの動作を行うようにしてほしい場合はtemplateを利用します。
default
マッピングされていないページに訪れたときに表示されるUIを記述します。並行ルートとの相性が良い機能となります。
loading
マッピング毎に設けられるSuspense境界で表示されるUIを記述するファイルです。
error
マッピング毎に設けられるErrorBoundary境界で表示されるUIを記述するファイルです。
global-error
app全体のエラーを扱うファイルです。app/layoutの内容すら置き換える内容を記述する必要があるのでhtml要素やbody要素を用いて記述する必要があります。
not-found
notFound関数がスローされたときやマッピングされていないページに訪れたときに表示されるUIを記述するファイルです。
route
マッピングされた場所でAPIを定義することができるファイルです。これまで紹介したファイルと一緒に置くことはできません。
ルーティングまとめ
これまで紹介したルーティングファイルは以下のような形で組み立てられます(routeとdefaultはここに記述されない)。
<ErrorBoundary fallback={<GlobalError />}>
<Layout>
<Template>
<ErrorBoundary fallback={<Error />}>
<Suspense fallback={<Loading />}>
<ErrorBoundary fallback={<NotFound />}>
<Page />
</ErrorBoundary>
</Suspense>
</ErrorBoundary>
</Template>
</Layout>
</ErrorBoundary>
icon
faviconやicon、apple-iconはappディレクトリに置くことでマッピングしたページのheadに追加してくれます。
これらはコードを用いて生成することもできます。
manifest.json
manifest.jsonやmanifest.webmanifestをappは以下に置くことでアプリに関する情報を提供できます。
これらはコードを用いて生成することもできます。
opengraph-image
opengraph-imageやtwitter-imageを設定することができます。
これらはコードを用いて生成することもできます。
robots.txt
robots.txtを設定することができます。
これらはコードを用いて生成することもできます。
sitemap.xml
sitemap.xmlを設定することができます。
これらはコードを用いて生成することもできます。
フォルダ
通常
App Routerはappディレクトリ内で配置されたディレクトリ構成をもとにルーティングを行います。
app/blogに置かれたファイルはexample.com/blogで展開されます。app/user/profileだとexample.com/user/profileです。
動的ルート
example.com/accounts/123やexample.com/accounts/987のように動的にパスが変更されるページを表現するには[]で囲むことで作成できます。例で出したケースはapp/accounts/[id]のように書きます。
このようなパスはexample.com/accounts/123/editのようなパスにはマッチしませんが、app/accounts/[...id]のように...を加えることでapp/accounts/:idに後続する全てのルートに一致するようになります。これはキャッチオールセグメントと呼ばれます。
そして、大括弧を一個増やしてapp/accounts/[[id]]のように書くことでexample.com/accounts/987だけではなく、example.com/accountsもマッチするようになります。この記法はキャッチオールセグメントと重ねて利用することもできます。
動的ルートがマッピングする先に通常のルーティングがマッピングされている場合は通常のマッピングが優先されることに注意してください。app/accounts/passwordでマッピングされている場合はexample.com/accounts/passwordにはapp/accounts/[id]ではなく、app/accounts/passwordの内容が反映されます。
ルートグループ
ルートグループは()を囲むことで利用できるマッピングに関する機能です。app/(royal)/accountsの内容はexample.com/accountsにマッピングされます。
App Routerではレイアウトなどの情報をより上位のディレクトリから引き継いで表示されますが、途中で引き継ぐ内容を分割したいことがあります。example.com/postsやexample.com/aboutより下のレベルとexample.com/accountsより下のレベルで異なる内容を表示したいとします。それぞれのディレクトリにレイアウトなどの情報を書くだけでも良いですが、ルートグループを用いることで、app/(public)/postsやapp/(public)/about、app/(private)/accountsのようにすることでpostsとaboutの共通化をしつつも異なる設定をaccountsに対して行うことができます。
並行ルート
並行ルートは@で始まる名前でディレクトリを作成することで利用できる機能です。app/@helloやapp/@worldのようにディレクトリを作成するとapp配下にあるレイアウトでそれらを用いることが可能となります。
app/@hello/accountsのように内部でディレクトリを積み重ねこともできます。しかし、app/accountsとapp/@hello/accountsディレクトリにファイルを置いて/accountsにアクセスしてもapp/@world/accountsにUIが宣言されていないため404ページが表示されます(ただし、Nextjsのナビゲーション機能を用いて遷移した場合はその部分に直前まで表示していたUIを表示し続けます)。
/accountsに直接アクセスしたときであってもUIを表示させたい場合はapp/@world/accountsにUIを宣言するか、app/@worldにdefaultファイルを記述する必要があります。
インターセプトルート
インターセプトルートは(.)や(..)、(..)(..)、(...)などから始まる名前でディレクトリを作成することで利用できる機能です。
例えばapp/accounts、app/blog、app/accounts/(..)blogのようにマッピングされているときに、example.com/accountsからexample.com/blogにアクセスしたときにapp/accountsではなく、app/accounts/(..)blogの内容が表示されるようになります。
規則は相対パスと同じような感じで(.)は同じレベルの内容をインターセプトします。(..)はひとつ上のレベルの内容をインターセプトします。(..)(..)はふたつ上のレベルの内容をインターセプトします。(...)はapp配下の内容をインターセプトします。
プライベートフォルダ
_から始まるディレクト名のことをプライベートフォルダと言います。App Routerの理から外れたファイルを設置できます。_componentsのようにがルーティングから除外したいが、app内におきたいようなファイルを置くのがおすすめです。