⚙️

【Next.js】Route Segment Configのページレンダリング手法をまとめてみた

2024/02/15に公開

Next.js の App Router の Route Segment Config でページのレンダリングを制御する方法についてまとめてみました。

Next.js 14.1.0 で検証しています。
もし、間違いを見つけた場合は、ご指摘いただけると幸いです。

Route Segment Config とは

Next.js 13 App Router から追加された機能で、ページ全体のレンダリングを制御することができます。

layout.tsxpage.tsx,Route Handlerで以下のような設定をすることで、ページのレンダリングを制御することができます。
また、設定することによりfetchデフォルトの設定を変更することができます。

// 静的レンダリングを強制する
export const dynamic = 'force-static';

Router Segment Config は以下の 7 つの設定があります。

https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config

dynamic

dynamic はそのページを静的または動的にレンダリングするかを制御します。
layout.tsxpage.tsx,Route Handlerで以下のように宣言することで使用できます。

export const dynamic = '...';

ページ全体を制御するため、App Router 以前のPages Routerからのスムーズに移行することができますとのことです。

Good to know: The new model in the app directory favors granular caching control at the fetch request level over the binary all-or-nothing model of getServerSideProps and getStaticProps at the page-level in the pages directory. The dynamic option is a way to opt back in to the previous model as a convenience and provides a simpler migration path.

1. auto

export const dynamic = 'auto';

デフォルト。静的レンダリングになります。ですが、任意のコンポーネントはfetchを用いて動的にレンダリングすることができます。

2. force-dynamic

export const dynamic = 'force-dynamic';

完全に動的にレンダリングされるため、設定したページは SSR の挙動になります。
Pages RoutergetServerSideProps()を使用した場合と同じ挙動になります。

3. error

export const dynamic = 'error';

完全に静的なレンダリングを作成し、fetchは常にcacheを使用します。SSG と同じ挙動になります。
Pages RoutergetStaticProps()を使用した場合と同じ挙動になります。
もし、そのページの配下のコンポーネントがfetch(... ,{ cache:"no-store" })や動的関数を使用している場合は、ビルド時にエラーが発生します。
後述するfetchCacheの設定がfetchCache = 'only-cache'に、dynamicParamsデフォルトの設定dynamicParams = 'false'に設定されます。

dynamic = 'error' changes the default of dynamicParams from true to false. You can opt back into dynamically rendering pages for dynamic params not generated by generateStaticParams by manually setting dynamicParams = true.

4. force-static

export const dynamic = 'force-static';

強制的に静的なレンダリングを実行します。SSG と同じ挙動になります。
dynamic = 'error'との違いは、ビルド時にエラーを発生させない点です。
もし、cookie()header(),useSearchParam()などの動的な関数を使用している場合、それらの関数の返り値は空の値になります。

dynamic まとめ

4 つの設定があります。

  1. auto ... デフォルト
  2. force-dynamic ... SSR の挙動でgetServerSideProps()と同じ挙動になります。
  3. error ... SSG の挙動でgetStaticProps()と同じ挙動になります。
  4. force-static ... SSG の挙動でgetStaticProps()と同じ挙動になります。

dynamicParams

export const dynamicParams = true;
// or
export const dynamicParams = false;

generateStaticParamsを使用した際に生成されなかったパスに対しての挙動を制御します。

trueの場合は動的に生成。falseの場合は404ページを表示します。
デフォルトはtrueです。

dynamic と dynamicParams を組み合わせて使用すると挙動が変わります。

force-dynamic と true の組み合わせ

export const dynamic = 'force-dynamic';
export const dynamicParams = true;

generateStaticParamsで生成したページを含めてSSR の挙動になります。

auto と true の組み合わせ

export const dynamic = 'auto';
export const dynamicParams = true;

generateStaticParamsで生成したページはSSGの挙動になります。
generateStaticParamsで生成されなかったページは初回のみ SSRの挙動になり、以降はSSGの挙動になります。

error と true の組み合わせ

export const dynamic = 'error';
export const dynamicParams = true;

auto と同じく、generateStaticParamsで生成したページはSSGの挙動になります。
generateStaticParamsで生成されなかったページは初回のみ SSRの挙動になり、以降はSSGの挙動になります。

dynamicParams まとめ

truefalse で設定します。

true ... generateStaticParamsで生成されなかったページに対しても動的にレンダリングします。
false ... generateStaticParamsで生成されなかったページに対しては 404 ページを表示します。

revalidate

export const revalidate = ...;

ページの再生成を制御します。ISR と同じ挙動になります。
fetchに revalidateが設定されている場合、fetchの再実行が優先されます。

1. false

export const revalidate = false;

デフォルト。キャッシュを使用して再生成されません。SSG と同じ挙動になります。

2. 0

export const revalidate = 0;

fetchcacheの設定がない場合、SSR と同じ挙動になります。
dynamic = 'force-dynamic'と同じ挙動になります。

3. number

export const revalidate = 60;

指定した秒数後に再生成されます。

revalidate まとめ

false0number で設定します。

false ... SSG と同じ挙動になります。
0 ... fetchcacheの設定がない場合、SSR と同じ挙動になります。
number ... 指定した秒数後に再生成されます。

fetchCache

export const fetchCache = ...;

fetchのデフォルトの設定を変更したり、fetchのキャッシュを制御します。

1. auto

export const fetchCache = 'auto';

デフォルトcacheを使用し、動的関数を使用している場合はcacheを使用しません。

2. default-cache

export const fetchCache = 'default-cache';

基本的にcacheを使用します。no-storeが明示的に設定されている場合は、cacheを使用しません。
autoとの違いは、cookie()などの動的関数を使用していてもcacheを使用します。

3. only-cache

export const fetchCache = 'only-cache';

すべてのfetchcacheを使用します。no-storeが明示的に設定されている場合は、エラーが発生します。

4. force-cache

export const fetchCache = 'force-cache';

すべてのfetchcacheを使用します。no-storeが明示的に設定されている場合でも、cacheを使用します。

5. default-no-store

export const fetchCache = 'default-no-store';

基本的にcacheを使用しません。force-cacheが明示的に設定されている場合は、cacheを使用します。

6. only-no-store

export const fetchCache = 'only-no-store';

すべてのfetchcacheを使用しません。cacheが明示的に設定されている場合は、エラーが発生します。

7. force-no-store

export const fetchCache = 'force-no-store';

すべてのfetchcacheを使用しません。cacheが明示的に設定されている場合でも、cacheを使用しません。

fetchCache まとめ

7 つの設定があります。

  1. auto ... デフォルト
  2. default-cache ... 基本的にcacheを使用します。
  3. only-cache ... すべてのfetchcacheを使用します。no-storeが明示的に設定されている場合は、エラーが発生します。
  4. force-cache ... 強制的にすべてのfetchcacheを使用します。
  5. default-no-store ... 基本的にcacheを使用しません。
  6. only-no-store ... すべてのfetchcacheを使用しません。cacheが明示的に設定されている場合は、エラーが発生します。
  7. force-no-store ... 強制的にすべてのfetchcacheを使用しません。

runtime

export const runtime = 'nodejs';
// or
export const runtime = 'edge';

実行環境を選択できます。Cloudflare Workers などのエッジ環境にデプロイする場合に使用します。
edgeを使用した場合、revalidateなどの ISR の設定が動作しなくなります。

https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes

runtime まとめ

nodejsedge で設定します。

nodejs ... デフォルト
edge ... エッジ環境にデプロイする場合に使用します。

preferredRegion

export const preferredRegion = 'auto';
// 'auto' | 'global' | 'home' | ['iad1', 'sfo1']

リージョンを指定できます。デフォルトはallで、1番近いリージョンが選択されます。

maxDuration

export const maxDuration = 5;

Next.js 13.4.10 で追加された機能で、サーバー側のロジックを実行する最大時間を設定できます。

issue

dynamic = 'force-dynamic'fetchCache = 'force-no-store'などのcacheを使用しない設定を使用した場合、うまく動作しない場合が多々あります。
なので、cacheを使用したくない場合は、fetch{ cache: 'no-store' }を設定して使用したほうが良いかもしれません。

https://github.com/vercel/next.js/issues/51788

https://github.com/vercel/next.js/issues/49300

https://github.com/vercel/next.js/issues/43879

まとめ

いくつか意図した挙動にならないので、個別にfetchcacheを設定したほうがいいと思いました。
dynamic = errorfetchCache = 'only-cache'などは、エラーを発生させてくれるので完全な静的なページを作成する際には便利だと思いました。

最後に

検証してから記載していますが、間違いがあるかもしれません。
もし、間違いを見つけた場合は、ご指摘いただけると幸いです。
ありがとうございました。

GitHubで編集を提案

Discussion