ダイナミックルーティングとは
Next.js では、pages/books/[id].tsx
のようなファイル名でページを作成すると、1 つのファイルで、
/books/001
/books/002
/books/003
のようなパス (URL) によるアクセスをハンドルできます。 これを ダイナミックルーティング (Dynamic Routes) 機能と呼びます。
Next.js のページコンポーネント (/pages/xxx.tsx
) は、そのページのエントリポイント(ルートコンポーネント)となるため、通常の React コンポーネントとは違って、上位のコンポーネントから props 情報を渡すことができません。
そこで Next.js では、ページコンポーネントの実装ファイル内で getStaticProps
という関数を定義することで、ページコンポーネントに渡す props 情報を生成できるようにしています。
getStaticProps
内では、上記のような URL パラメータ情報(/books/[id]
の id
の部分の値)を取り出して、それを元に props 情報を生成できます。
この仕組みによって、Next.js のページコンポーネントは、1 つの .tsx
ファイルで、複数のページ (.html) を生成できるようになっています。
ダイナミックルーティングの実装(SSG の場合)
静的ジェネレーション (SSG: Static Generation)、つまり Web サイトのビルド時にすべての HTML ファイルを生成してしまうには、あらかじめどのようなパラメーター(上記の例では id
)でのアクセスが行われるかを把握した上で、各ページの内容を生成する必要があります。
これを実現するには、ページコンポーネントの実装ファイル (pages/*.tsx
) で、次のような async
関数を実装して export
します。
- getStaticPaths 関数
- URL のパラメーター部分(上記の例では
id
)で指定可能な値を返すように実装します。言い換えると、プリビルドすべきページの一覧情報を Next.js に教えてあげるための実装です。この関数は通常、Web サイトのビルド時にだけ実行されますが、開発サーバー (next dev
) 使用時はアクセス毎に呼び出されることに注意してください。 - getStaticProps 関数
- 指定されたパラメーターに対応するデータを返すように実装します。この値がページコンポーネントに引数として渡されます。この関数は通常、Web サイトのビルド時にだけ実行されますが、
getStaticPath
の戻り値のプロパティfallback
をtrue
、あるいは'blocking'
に設定した場合は、アクセス時に呼び出される可能性があります(後述のフォールバックの説明を参照)。
次の例では、/books/001
、/books/002
、/books/003
といった URL でアクセス可能な books/[id]
ページを定義しています。
フォールバック制御
fallback プロパティ
上記の例では、getStaticPaths
関数の戻り値の fallback
プロパティに false
をセットしていますが、この値は、想定外のパラメーターを指定された場合のフォールバック方法 を設定するために使用します。
fallback: false
- paths プロパティで指定したパラメーター以外でのアクセス時に、404 ページ (
pages/404.tsx
) を返します。 fallback: true
- paths プロパティで指定したパラメーター以外でのアクセス時に、サーバーサイドで
getStaticProps
を呼び出して動的にページを生成します。それ以降のアクセスは、そのページを返します。この機能を利用する場合は、Next.js サーバーで Web サイトをホスティングしている必要があります(next export
で HTML エクスポートした場合は動作しません)。サーバーサイドでのページ生成中は、Web ブラウザ側には瞬間的に「フォールバックページ」が表示されることになります。フォールバック表示中かどうかを判断するには、useRouter
フックを利用してisFallback
情報を参照します(後述)。 fallback: 'blocking'
true
を指定した場合とほぼ同じですが、サーバーサイドでの HTML 生成が終わってから初めて Web ブラウザにレスポンスが返されるところが異なります(なのでブロッキングという名前になっています)。true
を指定した場合は、フォールバック表示(Loading 表示など)を行うことができますが、'blocking'
を指定した場合は、フォールバック表示は行えません(実装は楽ですがユーザーへのレスポンスが遅くなります)。
getStaticProps でデータを生成できないときの処理
このフォールバック機能を有効にしているとき(fallback: true
あるいは fallback: 'blocking'
のとき)、getStaticProps
は Web サイトへのアクセス時に、未知のパラメーター(上記の例の場合は id
の値)を伴って呼び出される可能性があります。
それに対応する props オブジェクト (PageProps
) を生成できない場合は、次のいずれかの対応を行う必要があります。
- データが空であることを示すオブジェクト(空オブジェクトとか)を返して、ページコンポーネント内で適切にハンドルする
- 404 コード(と 404 ページ)を返す(
{ notFound: true }
を返す) - 別のパスにリダイレクトする(
{ redirect: ... }
を返す)
例えば、次の例では、対応する props オブジェクトを生成できない場合に、空のオブジェクト {}
を返すように実装しています。
潔く、404 ページを表示するのであれば、getStaticProps
関数の戻り値として { notFound: true }
を返すだけで OK です。
getStaticPaths
の戻り値で fallback: false
と設定している場合は、上記のような分岐処理は必要ありません。
パラメーターとして未知の値が指定された場合に、自動的に 404 が返されます(getStaticProps
が呼び出されることがありません)。不正なパラメーターを指定された時に別の URL へリダイレクトしてしまいたい場合は、戻り値で redirect
プロパティを指定します。
フォールバック時のキャッシュの有効時間
フォールバックを有効にしているとき (fallback: true
)、未知のパラメーターでページアクセスがあると、Next.js サーバー側で getStaticProps
関数が呼び出されて、動的にページ生成が行われます。
このとき、次回以降のアクセスのために、生成されたページはキャッシュされるわけですが、このキャッシュの有効期間は getStaticProps
の戻り値の revalidate
プロパティで秒単位で設定することができます。
指定された秒数を経過後に、同じ URL にアクセスがあったときは、再度 getStaticProps
が呼び出されて、最新データでページが再構築されます。
逆に、revalidate
プロパティを設定しなかった場合は、最初に生成されたページがずーっと使われることになります。
revalidate
プロパティを指定してサーバーサイドで定期的にページを再構築することを、Next.js では ISR: Incremental Static Regeneration と呼んでいます。
フォールバック時の一時表示(フォールバックページ)
フォールバック有効時(fallback: true
のとき)、サーバーサイドで動的なページ生成が行われている最中(getStaticProps
実行中)は、クライアント側には「フォールバックページ」が表示されることになります。
フォールバックページでは、パラメーターとして渡される props
は空っぽになるので、代わりに適切な Loading 表示などを行う必要があります。
現在のページがフォールバック中であるかどうかを調べるには、useRouter
フックを使って、isFallback
の値をチェックします。
ダイナミックルーティングの実装(SSR の場合)
すべてのページを Web サーバーへのアクセス時に動的に生成することを、サーバーサイドレンダリング (SSR: Server-side Rendering) と呼びます。
ダイナミックルーティング機能を SSR で使用するには、getStaticPaths
関数や getStaticProps
関数の代わりに次の関数を実装します。
- getServerSideProps 関数
- Web サーバー(Next.js サーバー)へのアクセス時に呼び出されます。
context.params
を参照すると URL で指定されたパラメーター (id
) を取得できるので、それに対応するデータを返すように実装します。このデータはページコンポーネントの引数として渡されます。
実装方法は getStaticProps
と同様です。
この関数は Web サーバーへのアクセス時に呼び出されるため、必ず Web サイトを Next.js サーバーでホスティングする必要があります(next export
で静的な HTML ファイルとしてエクスポートした場合は動作しません)。
Next.js アプリのホスティングサービスとしては、Vercel が有名です。
SSR の仕組み (getServerSideProps
) を使うと、Web ページへのアクセス時に毎回ページ生成が行われるため、クライアントへのレスポンスはどうしても遅くなります。
常に最新の情報を使ってページ生成を行う必要がないのであれば、できるだけ SSG: Static Generation によるレンダリングを行うべきです(getServerSideProps
ではなく getStaticProps
を実装する)。
getStaticProps
でも、戻り値の revalidate
プロパティを設定すれば、定期的にページを再構築できます (ISR)。