メインコンテンツまでスキップ

Next.jsのキャッシュ

Next.jsは、レンダリング作業やデータリクエストをキャッシュすることで、アプリケーションのパフォーマンスを向上させ、コストを削減します。このページでは、Next.jsのキャッシングメカニズム、またそれらを設定するために使用できるAPI、およびそれらがどのように相互作用するかについて詳しく説明します。

Good to know: このページは、Next.jsが内部でどのように動作しているかを理解するのに役立ちますが、Next.jsを生産的に使用するための必須知識ではありません。ほとんどのNext.jsのキャッシングに関するユーリスティックは、APIの使用に基づいて決定され、最小限の設定で最高のパフォーマンスを発揮するためのデフォルトが設定されています。例を見たい場合は、こちらから始めてください

概要

以下は、さまざまなキャッシングメカニズムとその目的に関する高レベルの概要です:

メカニズム内容場所目的期間
Request Memoization関数の戻り値サーバーReact Component treeでデータを再利用するためリクエストライフサイクル中
Data Cacheデータサーバーユーザーリクエストやデプロイメント間でデータを保持永続的(再検証可能)
Full Route CacheHTMLとRSCペイロードサーバーレンダリングコストを削減し、パフォーマンスを向上させるため永続的(再検証可能)
Router CacheRSCペイロードクライアントナビゲーション時のサーバーリクエストを削減するためユーザーセッションまたは時間に基づく

Next.jsは、デフォルトでパフォーマンスを向上させコストを削減するために、できる限り多くのキャッシュを行います。つまり、ルートは静的にレンダリングされ、データリクエストはキャッシュされますが、これは任意で無効にできます。以下のダイアグラムは、ビルド時にルートが静的にレンダリングされるおよび静的なルートが最初に訪れられたときのデフォルトのキャッシング動作を示しています。

Next.jsのデフォルトキャッシング動作を示す図で、ビルド時と最初の訪問時のHIT、MISS、SETを示しています。Next.jsのデフォルトキャッシング動作を示す図で、ビルド時と最初の訪問時のHIT、MISS、SETを示しています。

キャッシング動作は、ルートが静的か動的か、データがキャッシュされているかされていないか、リクエストが初回訪問の一部なのか後続のナビゲーションによるものかによって変わります。ユースケースに応じて、個々のルートやデータリクエストのキャッシング動作を設定することができます。

リクエストメモ化

Reactは、同じURLとオプションを持つリクエストを自動的にメモ化するためにfetch APIを拡張しています。これにより、Reactコンポーネントtree内の複数の場所で同じデータを取得するためのfetch関数を呼び出すことができますが、実行されるのは1度だけです。

重複排除されたFetchリクエスト重複排除されたFetchリクエスト

例えば、ルート全体で同じデータが必要な場合(例えば、Layout、Page、および複数のコンポーネントにおいて)、treeの最上部でデータをfetchし、コンポーネント間でpropsを転送する必要はありません。その代わりに、必要なコンポーネント内でデータを取得でき、同じデータに対するネットワーク上での複数リクエストのパフォーマンスへの影響を心配する必要はありません。

app/example.tsx
async function getItem() {
// `fetch`関数は自動的にメモ化され、その結果はキャッシュされます
const res = await fetch('https://.../item/1')
return res.json()
}

// この関数は2回呼び出されますが、最初の1回のみ実行されます
const item = await getItem() // cache MISS

// 二度目の呼び出しはルート内のどこでも可能です
const item = await getItem() // cache HIT

リクエストメモ化の仕組み

Reactレンダリング中にfetchメモ化がどのように機能するかを示すダイアグラム。Reactレンダリング中にfetchメモ化がどのように機能するかを示すダイアグラム。
  • ルートをレンダリングする際に、特定のリクエストが初めて呼び出されたとき、その結果はメモリに存在せず、キャッシュのMISSとなります。
  • したがって、関数が実行され、データが外部ソースから取得され、その結果がメモリに格納されます。
  • 同じレンダーパス内でのリクエストの後続の関数呼び出しはキャッシュのHITとなり、関数を実行することなくメモリからデータが返されます。
  • ルートがレンダリングされ、レンダリングパスが完了すると、メモリは「リセット」され、すべてのリクエストメモ化エントリがクリアされます。

Good to know:

  • リクエストメモ化はReactの機能であり、Next.jsの機能ではありません。ここでは、他のキャッシングメカニズムとの相互作用を示すために含まれています。
  • メモ化はfetchリクエストのGETメソッドにのみ適用されます。
  • メモ化はReact Component treeにのみ適用されます。つまり:
    • generateMetadatagenerateStaticParams、Layouts、Pages、およびその他のServer Components内のfetchリクエストに適用されます。
    • Route Handlers内のfetchリクエストには適用されません。なぜなら、それらはReact component treeの一部ではないからです。
  • fetchが適さない場合(例:一部のデータベースクライアント、CMSクライアント、GraphQLクライアント)、関数をメモ化するためにReactのcache関数を使用できます。

期間

キャッシュはサーバーリクエストのライフタイムが続く間、つまりReact component treeのレンダリングが完了するまで持続します。

再検証

メモ化はサーバーリクエスト間で共有されず、レンダリング中のみに適用されるため、再検証する必要はありません。

オプトアウト

メモ化はfetchリクエストのGETメソッドにのみ適用され、POSTDELETEなどの他のメソッドはメモ化されません。このデフォルトの動作はReactの最適化であり、オプトアウトすることをお勧めしません。

個々のリクエストを管理するには、AbortControllersignalプロパティを使用できます。ただし、これはメモ化からオプトアウトするのではなく、実行中のリクエストを中止するものです。

app/example.js
const { signal } = new AbortController()
fetch(url, { signal })

データキャッシュ

Next.jsには組み込みのデータキャッシュがあり、データの取得結果をサーバーリクエストデプロイメント間で保持します。これは、Next.jsがネイティブのfetch APIを拡張し、サーバー上の各リクエストが独自の永続的なキャッシングセマンティクスを設定できるようにすることで可能です。

Good to know: ブラウザでは、fetchcacheオプションはリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示しますが、Next.jsでは、cacheオプションはサーバー側のリクエストがサーバーのデータキャッシュとどのように相互作用するかを示します。

fetchcacheおよびnext.revalidateオプションを使用して、キャッシング動作を設定できます。

データキャッシュの仕組み

データキャッシュと対話するキャッシュおよび非キャッシュのfetchリクエストの図。キャッシュリクエストはデータキャッシュに格納され、メモ化されます。非キャッシュリクエストはデータソースから取得され、データキャッシュに格納されず、メモ化されます。データキャッシュと対話するキャッシュおよび非キャッシュのfetchリクエストの図。キャッシュリクエストはデータキャッシュに格納され、メモ化されます。非キャッシュリクエストはデータソースから取得され、データキャッシュに格納されず、メモ化されます。
  • 'force-cache'オプション付きのfetchリクエストがレンダリング中に初めて呼び出されたとき、Next.jsはデータキャッシュにキャッシュされた応答があるか確認します。
  • キャッシュされた応答が見つかった場合、それはすぐに返され、メモ化されます
  • キャッシュされた応答が見つからなかった場合、リクエストがデータソースに送られ、その結果がデータキャッシュに保存され、メモ化されます。
  • 非キャッシュデータ(例:cacheオプションが定義されていないまたは{ cache: 'no-store' }を使用)は、結果が常にデータソースから取得され、メモ化されます。
  • データがキャッシュされているかどうかにかかわらず、同じデータに対する重複したリクエストを防ぐためにリクエストは常にメモ化され、Reactレンダリングパス中に行われます。

データキャッシュとリクエストメモ化の違い

両方のキャッシングメカニズムは、キャッシュされたデータを再利用することによってパフォーマンスを向上させますが、データキャッシュはリクエストとデプロイメントにまたがって永続的に維持されるのに対し、メモ化はリクエストのライフタイム内でのみ持続します。

期間

データキャッシュは、再検証またはオプトアウトが行われない限り、リクエストやデプロイメント間で永続的に保持されます。

再検証

キャッシュされたデータは次の2つの方法で再検証できます:

  • 時間ベースの再検証: 一定時間経過後の新しいリクエストでデータを再検証します。これは、データがあまり頻繁に変化せず、新鮮さがあまり重要でない場合に有用です。
  • オンデマンドの再検証: イベントに基づいてデータを再検証します(例:フォーム送信)。オンデマンドの再検証はタグベースまたはパスベースのアプローチを使用してデータのグループを一度に再検証できます。例えば、無頭CMSのコンテンツが更新されたときに最新のデータをすぐに表示したい場合に有効です。

時間ベースの再検証

特定の時間間隔でデータを再検証するには、fetchにおけるnext.revalidateオプションを使用して、リソースのキャッシュライフタイム(秒単位)を設定します。

// 最大で毎時再生性を検証
fetch('https://...', { next: { revalidate: 3600 } })

または、ルートセグメント設定オプションを使用して、セグメント内のすべてのfetchリクエストを設定したり、fetchを使用できない場合に設定できます。

時間ベースの再検証の仕組み

時間ベースの再検証の仕組みを示す図で、再検証期間後、最初のリクエストに対して古いデー�タが返され、次にデータが再検証されます。時間ベースの再検証の仕組みを示す図で、再検証期間後、最初のリクエストに対して古いデータが返され、次にデータが再検証されます。
  • fetchリクエストが最初にrevalidateを指定して呼び出されたとき、外部データソースからデータが取得され、データキャッシュに保存されます。
  • 指定された時間枠内に呼び出されたリクエストは、キャッシュされたデータを返します。
  • 時間枠が経過した後、次のリクエストはまだキャッシュ(現在は古い)データを返します。
    • Next.jsはバックグラウンドでデータの再検証をトリガーします。
    • データが正常に取得されると、Next.jsは新鮮なデータでデータキャッシュを更新します。
    • バックグラウンド再検証が失敗した場合、前のデータはそのまま残ります。

これはstale-while-revalidate動作に似ています。

オンデマンド再検証

データはパスごとに(revalidatePath)またはキャッシュタグごとに(revalidateTag)オンデマンドで再検証できます。

オンデマンド再検証の仕組み

オンデマンド再検証の仕組みを示す図で、データキャッシュが再検証リクエスト後に新鮮なデータで更新される仕組みを示します。オンデマンド再検証の仕組みを示す図で、データキャッシュが再検証リクエスト後に新鮮なデータで更新される仕組みを示します。
  • fetchリクエストが初めて呼び出されたとき、データが外部データソースから取得され、データキャッシュに保存されます。
  • オンデマンド再検証がトリガーされると、適切なキャッシュエントリはキャッシュから削除されます。
    • これは、古いデータをキャッシュに保持する時間ベースの再検証とは異なり、データが取得されるまでキャッシュに残ります。
  • 次回のリクエストが行われたとき、再びキャッシュのMISSとなり、データが外部データソースから取得され、データキャッシュに保存されます。

オプトアウト

fetchからの応答をキャッシュしたくない場合、以下のようにできます:

let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })

フルルートキャッシュ

関連する用語

自動静的最適化、静的サイト生成、または静的レンダリングという用語が、アプリケーションのルートをビルド時にレンダリングおよびキャッシュするプロセスを指すために互換的に使用されることがあります。

Next.jsはデフォルトでルートをビルドタイムにレンダリングし、キャッシュします。これは、個々のリクエストごとにサーバーでレンダリングする代わりにキャッシュされたルートを提供できる最適化であり、高速なページ読み込みを実現します。

フルルートキャッシュがどのように機能するかを理解するために、Reactがレンダリングをどのように扱うか、およびNext.jsがその結果をどのようにキャッシュするかを見ると役立ちます:

1. サーバーにおけるReactレンダリング

サーバーでは、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントおよびSuspenseバウンダリーごとに分割されます。

各チャンクは2つのステップでレンダリングされます:

  1. ReactはServer Componentsをストリーミングに最適化された特別なデータフォーマットにレンダリングします。これはReact Server Component Payloadと呼ばれます。
  2. Next.jsはReact Server Component PayloadとクライアントのJavaScript命令を使用して、サーバー上でHTMLをレンダリングします。

これにより、すべてがレンダリングされるのを待たずに作業をキャッシュしたり、応答を送信することができます。代わりに、作業が完了するたびに応答をストリーミングできるようになります。

React Server Component Payloadとは何か?

React Server Component Payloadは、レンダリングされたReact Server Components treeのコンパクトなバイナリ表現です。クライアント上のReactにより、ブラウザのDOMを更新するために使用されます。React Server Component Payloadには以下が含まれます:

  • Server Componentsのレンダリング結果
  • クライアント ComponentsのJavaScriptファイルのプレースホルダーとその参照
  • Server Componentsからクライアント Componentsに渡されたprops

詳細は、Server Componentsのドキュメントをご覧ください。

2. サーバーでのNext.jsキャッシング(フルルートキャッシュ)

Next.jsのデフォルトのフルルートキャッシュの動作を示しており、React Server Component PayloadとHTMLがサーバーでキャッシュされる様子を示しています。Next.jsのデフォルトのフルルートキャッシュの動作を示しており、React Server Component PayloadとHTMLがサーバーでキャッシュされる様子を示しています。

Next.jsのデフォルトの動作は、ルートのレンダリング結果(React Server Component PayloadとHTML)をサーバーでキャッシュすることです。これはビルドタイムや再検証時に静的にレンダリングされたルートに適用されます。

3. クライアントでのReact実行と同期

リクエスト時にクライアントでは:

  1. HTMLは、クライアントとServer Componentsの非対話型の初期プレビューをすぐに表示するために使用されます。
  2. React Server Components Payloadは、クライアントとレンダリングされたServer Component treesを統合して、DOMを更新するために使用されます。
  3. JavaScript命令は、クライアント Componentsを実行してアプリケーションを対話型にします。

4. クライアントでのNext.jsキャッシング(ルーターキャッシュ)

React Server Component Payloadは、クライアント側のRouter Cacheに格納されます。これは、個々のルートセグメントごとに分割されたメモリキャッシュです。このRouter Cacheは、以前に訪問したルートを保存し、将来的に訪問する可能性のあるルートを事前に取得するために使用されます。

5. 後続のナビゲーション

後続のナビゲーションや事前取得中、Next.jsはRouter CacheにReact Server Components Payloadが保存されているかどうかを確認します。保存されている場合は、新しいサーバーリクエストを送信することをスキップします。

ルートセグメントがキャッシュにない場合、Next.jsはサーバーからReact Server Components Payloadを取得し、クライアントのRouter Cacheに追加します。

静的と動的レンダリング

ルートがビルドタイムにキャッシュされるかどうかは、そのルートが静的または動的にレンダリングされるかどうかに依存します。静的ルートはデフォルトでキャッシュされ、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。

以下の図は、静的および動的にレンダリングされたルートの違いを示しており、キャッシュデータと非キャッシュデータが示されています:

静的および動的レンダリングがフルルートキャッシュに与える影響を示す図。静的ルートはビルドタイムまたはデータ再検証後にキャッシュされ、動的ルートは決してキャッシュされない。静的および動的レンダリングがフルルートキャッシュに与える影響を示す図。静的ルートはビルドタイムまたはデータ再検証後にキャッシュされ、動的ルートは決してキャッシュされない。

静的および動的レンダリングについて詳しく学ぶ。

期間

デフォルトでは、フルルートキャッシュは永続的です。これは、レンダー出力がユーザーリクエスト間でキャッシュされることを意味します。

無効化

フルルートキャッシュを無効化する方法は2つあります:

  • データの再検証: データキャッシュを再検証すると、サーバー上でコンポーネントが再レンダリングされ、新しいレンダー出力がキャッシュされることでRouter Cacheも無効化されます。
  • 再デプロイ: データキャッシュとは異なり、フルルートキャッシュは新しいデプロイメント時にクリアされます。

オプトアウト

フルルートキャッシュからオプトアウトすることができます。言い換えれば、各インカミングリクエストごとにコンポーネントを動的にレンダリングすることができます:

  • 動的APIの使用: これはフルルートキャッシュからルートをオプトアウトし、リクエスト時に動的にレンダリングされることを意味します。データキャッシュは依然として使用できます。
  • ** dynamic = 'force-dynamic'またはrevalidate = 0 ルートセグメント設定オプションを使用する**: これはフルルートキャッシュおよびデータキャッシュをスキップします。つまり、インカミングリクエストごとにサーバー上でコンポーネントがレンダリングされ、データが取得されます。ルートキャッシュはクライアント側のキャッシュであるため引き続き適用されます。
  • データキャッシュのオプトアウトfetchリクエストでキャッシュされないものがある場合、そのルートはフルルートキャッシュからオプトアウトします。特定のfetchリクエストに対して、インカミングリクエストごとにデータが取得されます。キャッシュオプトアウトしないその他のfetchリクエストは依然としてデータキャッシュにキャッシュされ続けます。これは、キャッシュされたデータとキャッシュされていないデータが共存するハイブリッドを可能にします。

クライアントサイドのルーターキャッシュ

Next.jsには、レイアウト、読み込み状態、ページごとに分割されたルートセグメントのRSCペイロードを格納するメモリ内クライアントサイドルーターキャッシュがあります。

ユーザーがルート間を移動するとき、Next.jsは訪問したルートセグメントをキャッシュし、ユーザーが訪問する可能性があるルートを事前取得します。これにより、瞬時のバック/フォワードナビゲーション、ナビゲーション間の全ページ更新の不要、React状態やブラウザ状態の保持が実現されます。

ルーターキャッシュを使用することで:

  • レイアウトはキャッシュされ、ナビゲーション時に再利用されます(部分レンダリング)。
  • 読み込み状態はルート間の瞬時のナビゲーションのためにキャッシュされ再利用されます(瞬時読み込み状態)。
  • ページ はデフォルトでキャッシュされませんが、ブラウザの前後のナビゲーション時に再利用されます。実験オプションstaleTimesを使ってページセグメントをキャッシュすることができます。

Good to know: このキャッシュはNext.jsとServer Componentsに特有であり、ブラウザのbfcacheとは異なりますが、似たような結果をもたらします。

期間

キャッシュはブラウザの一時メモリに格納されます。2つの要因がルーターキャッシュの存続期間を決定します:

  • セッション: ナビゲーション中にキャッシュは持続します。ただし、ページの再読み込みでクリアされます。
  • 自動無効化期間: レイアウトと読み込み状態のキャッシュは、指定された時間後に自動的に無効化されます。期間は、リソースがどのように事前取得されたか、そしてリソースが静的に生成されたかに依存します:
    • デフォルトの事前取得prefetch={null}または指定なし): 動的ページにはキャッシュされません、静的ページには5分間。
    • 完全な事前取得prefetch={true}またはrouter.prefetch): 静的および動的ページの両方に対して5分間。

ページの再読み込みはすべてのキャッシュセグメントをクリアしますが、自動無効化期間は、事前取得された時間からの個々のセグメントのみに影響します。

Good to know: 実験オプションstaleTimesを使用して上記の自動無効化時間を調整することができます。

無効化

ルーターキャッシュを無効化する方法は次の2つです:

  • Server Action の中で:
    • パスでのオンデマンド再検証は(revalidatePath)タグでのキャッシュ再検証は(revalidateTag
    • cookies.setまたはcookies.deleteを使用してルーターキャッシュを無効にし、クッキーを使用するルートが古くなるのを防ぐ(例:認証)。
  • router.refreshを呼び出すことでルーターキャッシュを無効にし、現在のルートに対するサーバーへの新しいリクエストを行う。

オプトアウト

Next.js 15以降、ページセグメントはデフォルトでオプトアウトされています。

Good to know: <Link>コンポーネントのprefetchプロップをfalseに設定することで、事前取得をオプトアウトすることもできます。

キャッシュの相互作用

さまざまなキャッシングメカニズムを設定する際、相互作用を理解することが重要です:

データキャッシュとフルルートキャッシュ

  • データキャッシュを再検証またはオプトアウトすることは、フルルートキャッシュを無効化します。なぜなら、レンダー出力はデータに依存しているからです。
  • フルルートキャッシュを無効化またはオプトアウトしても、データキャッシュには影響しません。キャッシュされたデータとキャッシュされていないデータの両方を持つルートを動的にレンダリングできます。たとえば、ほとんどのページがキャッシュされたデータを使用する場合でも、いくつかのコンポーネントがリクエスト時に取得する必要のあるデータに依存していることに有用です。すべてのデータを再取得する際のパフォーマンスへの影響を心配せずに動的レンダリングできます。

データキャッシュとクライアントサイドのルーターキャッシュ

  • データキャッシュとルーターキャッシュを即座に無効化するにはServer ActionrevalidatePathまたはrevalidateTagを使用できます。
  • Route Handlerでデータキャッシュを再検証しても、Router Cacheは直ちには無効化されません。これらのRoute Handlerは特定のルートに結び付けられていないため、Router Cacheはハードリフレッシュまたは自動無効化期間が経過するまで以前のペイロードを提供し続けます。

API

次の表は、さまざまなNext.js APIがキャッシングにどのような影響を与えるかの概要を示しています:

APIRouter CacheフルルートキャッシュData CacheReact Cache
<Link prefetch>Cache
router.prefetchCache
router.refreshRevalidate
fetchCacheCache
fetch options.cacheCache or Opt out
fetch options.next.revalidateRevalidateRevalidate
fetch options.next.tagsCacheCache
revalidateTagRevalidate (Server Action)RevalidateRevalidate
revalidatePathRevalidate (Server Action)RevalidateRevalidate
const revalidateRevalidate or Opt outRevalidate or Opt out
const dynamicCache or Opt outCache or Opt out
cookiesRevalidate (Server Action)Opt out
headers, searchParamsOpt out
generateStaticParamsCache
React.cacheCache
unstable_cacheCache

デフォルトでは、<Link>コンポーネントはフルルートキャッシュからルートを自動的に事前取得し、Router CacheにReact Server Component Payloadを追加します。

事前取得を無効にするには、prefetchプロパティをfalseに設定します。ただし、これはキャッシュを永続的にスキップすることはなく、ユーザーがルートを訪問したときにルートセグメントはクライアント側でキャッシュされます。

<Link>コンポーネントの詳細を学ぶ。

router.prefetch

useRouterフックのprefetchプロパティを使用して、ルートを手動で事前取得できます。これにより、Router CacheにReact Server Component Payloadを追加します。

useRouterフックのAPIリファレンスを参照してください。

router.refresh

useRouterフックのrefreshプロパティを使用して、ルートを手動で更新できます。これによりRouter Cacheが完全にクリアされ、現在のルートに対するサーバーへの新しいリクエストが行われます。refreshはデータキャッシュまたはフルルートキャッシュには影響を与えません。

描画結果はクライアント側で統合され、React状態やブラウザ状態が保持されます。

useRouterフックのAPIリファレンスを参照してください。

fetch

fetchから返されたデータは、自動的にデータキャッシュにキャッシュされます。

fetchからの応答をキャッシュしたくない場合、以下のようにできます:

let data = await fetch('https://api.vercel.app/blog', { cache: 'no-store' })

fetch APIリファレンスでその他のオプションを確認してください。

fetch options.cache

個々のfetchをキャッシュにオプトインする場合、cacheオプションをforce-cacheに設定します:

// キャッシュにオプトイン
fetch(`https://...`, { cache: 'force-cache' })

fetch APIリファレンスでその他のオプションを確認してください。

fetch options.next.revalidate

fetchnext.revalidateオプションを使用して、個々のfetchリクエストの再検証期間(秒単位)を設定することができます。これによりデータキャッシュが再検証され、結果としてフルルートキャッシュも再検証されます。新鮮なデータが取得され、コンポーネントがサーバー上で再レンダリングされます。

// 最大1時間後に再検証
fetch(`https://...`, { next: { revalidate: 3600 } })

fetch APIリファレンスでその他のオプションを確認してください。

fetch options.next.tags and revalidateTag

Next.jsには、細かなデータキャッシングと再検証のためのキャッシュタグシステムがあります。

  1. fetchunstable_cacheを使用するときに、キャッシュエントリを1つ以上のタグでタグ付けするオプションがあります。
  2. その後、タグに関連付けられたキャッシュエントリを削除するためにrevalidateTagを呼び出すことができます。

たとえば、データを取得する際にタグを設定できます:

// データをタグでキャッシュ
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

次に、特定のタグを持つキャッシュエントリを削除してrevalidateTagを呼び出します:

// 特定のタグを持つエントリを再検証
revalidateTag('a')

使用目的によって、revalidateTagを次の場所で使用できます:

  1. Route Handlers - サードパーティーイベント(例:Webhook)の応答としてデータを再検証する。

  2. Server Actions - ユーザーアクション(例:フォーム送信)後にデータを再検証する。 この場合、関連するルートのRouter Cacheは無効化されます。

revalidatePath

revalidatePathを使って、特定のパス以下のルートセグメントを再レンダリングしつつデータを手動で再検証することが可能です。このメソッドを呼び出すことでデータキャッシュが再検証され、その結果フルルートキャッシュも無効化されます。

revalidatePath('/')

使用目的によって、revalidatePathを次の場所で使用できます:

  1. Route Handlers - サードパーティーイベント(例:Webhook)の応答としてデータを再検証する。
  2. Server Actions - ユーザーインタラクション(例:フォーム送信、ボタンのクリック)後にデータを再検証する。

revalidatePath APIリファレンスで詳細を確認してください。

revalidatePathrouter.refresh

router.refreshを呼び出すと、Router Cacheがクリアされ、サーバー上でルートセグメントが再レンダリングされますが、データキャッシュやフルルートキャッシュは無効化されません。

revalidatePathはデータキャッシュとフルルートキャッシュをクリアしますが、router.refresh()はデータキャッシュとフルルートキャッシュを変更しないという違いがあります。

動的API

cookiesheadersのような動的API、およびPages内のsearchParamsプロップは実行時のインカミングリクエスト情報に依存します。これらを使用すると、ルートがフルルートキャッシュからオプトアウトし、つまり、ルートが動的にレンダリングされることになります。

cookies

Server Action内でcookies.setまたはcookies.deleteを使用すると、それを使用するルートが古くならないように、Router Cacheを無効にします(例:認証の変更を反映するため)。

cookies APIリファレンスを参照してください。

セグメント設定オプション

ルートセグメント設定オプションは、fetch APIを使用できない場合(例:データベースクライアントやサードパーティライブラリ)またはデフォルトを上書きする場合に、ルートセグメントの設定をオーバーライドするために使用できます。

次のルートセグメント設定オプションはフルルートキャッシュをオプトアウトします:

  • const dynamic = 'force-dynamic'

この設定オプションは、すべてのフェッチをデータキャッシュからオプトアウトします(すなわちno-store):

  • const fetchCache = 'default-no-store'

fetchCacheでより高度なオプションを確認してください。

ルートセグメント設定のドキュメントで詳細なオプションを確認してください。

generateStaticParams

動的セグメント(例:app/blog/[slug]/page.js)について、generateStaticParamsによって提供されるパスはビルドタイムにフルルートキャッシュにキャッシュされます。リクエスト時にNext.jsはビルドタイムに知られていなかったパスを初めて訪問した際にもキャッシュします。

ビルドタイムにすべてのパスを静的にレンダリングするには、generateStaticParamsにパスの完全なリストを提供します:

app/blog/[slug]/page.js
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())

return posts.map((post) => ({
slug: post.slug,
}))
}

ビルドタイムに一部のパスを静的にレンダリングし、残りは実行時に初めて訪問したときにレンダリングするには、部分的なパスのリストを返します:

app/blog/[slug]/page.js
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())

// ビルドタイムに最初の10投稿をレンダリングする
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}))
}

訪問時に初めてすべてのパスを静的にレンダリングするには、空の配列を返します(ビルドタイムにはパスはレンダリングされませnん)またはexport const dynamic = 'force-static'を利用します:

app/blog/[slug]/page.js
export async function generateStaticParams() {
return []
}

Good to know: generateStaticParamsから配列を返す必要があります。たとえそれが空でもそうです。さもなければ、ルートは動的にレンダリングされます。

app/changelog/[slug]/page.js
export const dynamic = 'force-static'

リクエスト時のキャッシングを無効にするには、ルートセグメントにexport const dynamicParams = falseオプションを追加します。この設定オプションが使用された場合、generateStaticParamsによって提供されたパスのみが提供され、その他のルートは404になったり(一致した場合にはcatch-all routes)になります。

React cache関数

Reactのcache関数を使用すると、関数の戻り値をメモ化でき、同じ関数を複数回呼び出しながらも、一度だけ実行することができます。

fetchリクエストは自動的にメモ化されるため、React cacheでラップする必要はありませんが、fetch APIが適さない場合にデータリクエストを手動でメモ化するためにcacheを使用することができます。例えば、一部のデータベースクライアント、CMSクライアント、またはGraphQLクライアントなどの場合。

utils/get-item.ts
import { cache } from 'react'
import db from '@/lib/db'

export const getItem = cache(async (id: string) => {
const item = await db.item.findUnique({ id })
return item
})