コンテンツにスキップ

Next.js のキャッシュ

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

知っておくと良いこと: このページは、Next.js がどのように動作するかを理解するのに役立ちますが、Next.js を活用するために必須の知識ではありません。Next.js のほとんどのキャッシュヒューリスティックは、API の使用状況によって決定され、ゼロまたは最小限の設定で最高のパフォーマンスが得られるようにデフォルトが設定されています。代わりに例をすぐに見たい場合は、ここから始めてください。

概要

さまざまなキャッシュメカニズムとその目的の概要を以下に示します。

メカニズム内容場所目的期間
リクエストのメモ化関数の戻り値サーバーReact コンポーネントツリーでデータを再利用リクエストごとのライフサイクル
データキャッシュデータサーバーユーザーリクエストとデプロイメント間でデータを保存永続的 (再検証可能)
フルルートキャッシュHTML および RSC ペイロードサーバーレンダリングコストを削減し、パフォーマンスを向上永続的 (再検証可能)
ルーターキャッシュRSC ペイロードクライアントナビゲーション時のサーバーリクエストを削減ユーザーセッションまたは時間ベース

デフォルトでは、Next.js はパフォーマンスを向上させ、コストを削減するために可能な限りキャッシュします。つまり、ルートは 静的にレンダリング され、データリクエストはオプトアウトしない限り キャッシュ されます。次の図は、デフォルトのキャッシュ動作を示しています。ルートがビルド時に静的にレンダリングされる場合と、静的ルートが最初にアクセスされた場合です。

Diagram showing the default caching behavior in Next.js for the four mechanisms, with HIT, MISS and SET at build time and when a route is first visited.

キャッシュ動作は、ルートが静的にレンダリングされるか動的にレンダリングされるか、データがキャッシュされるかキャッシュされないか、およびリクエストが最初のアクセスの一部か後続のナビゲーションの一部かによって異なります。ユースケースに応じて、個々のルートおよびデータリクエストのキャッシュ動作を構成できます。

リクエストのメモ化

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

Deduplicated Fetch Requests

たとえば、ルート全体で同じデータを使用する必要がある場合 (例: レイアウト、ページ、複数のコンポーネント)、ツリーの最上部でデータをフェッチし、コンポーネント間でプロパティを転送する必要はありません。代わりに、ネットワークを介して同じデータの複数のリクエストを行うパフォーマンスへの影響を心配することなく、必要なコンポーネントでデータをフェッチできます。

app/example.tsx
async function getItem() {
  // The `fetch` function is automatically memoized and the result
  // is cached
  const res = await fetch('https://.../item/1')
  return res.json()
}
 
// This function is called twice, but only executed the first time
const item = await getItem() // cache MISS
 
// The second call could be anywhere in your route
const item = await getItem() // cache HIT

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

Diagram showing how fetch memoization works during React rendering.
  • ルートのレンダリング中に、特定のリクエストが最初に呼び出されるとき、その結果はメモリに存在せず、キャッシュ MISS になります。
  • したがって、関数が実行され、データが外部ソースからフェッチされ、結果がメモリに格納されます。
  • 同じレンダリングパスでの後続のリクエスト関数の呼び出しは、キャッシュ HIT になり、関数を実行せずにメモリからデータが返されます。
  • ルートがレンダリングされ、レンダリングパスが完了すると、メモリが「リセット」され、すべてのリクエストメモ化エントリがクリアされます。

知っておくと良いこと:

  • リクエストのメモ化は、Next.js の機能ではなく、React の機能です。これは、他のキャッシュメカニズムとどのように相互作用するかを示すためにここに含まれています。
  • メモ化は、fetch リクエストの GET メソッドにのみ適用されます。
  • メモ化は、React コンポーネントツリーにのみ適用されます。つまり
    • generateMetadatagenerateStaticParams、レイアウト、ページ、およびその他のサーバーコンポーネントの fetch リクエストに適用されます。
    • React コンポーネントツリーの一部ではないため、ルートハンドラーの fetch リクエストには適用されません。
  • fetch が適切でない場合(例えば、一部のデータベースクライアント、CMSクライアント、またはGraphQLクライアントなど)、Reactのcache関数を使用して関数をメモ化できます。

期間

キャッシュは、Reactコンポーネントツリーのレンダリングが完了するまで、サーバーリクエストのライフタイムの間だけ有効です。

再検証

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

オプトアウト

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

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

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

データキャッシュ

Next.jsには、着信サーバーリクエストおよびデプロイメント間でデータフェッチの結果を永続化する組み込みのデータキャッシュがあります。これは、Next.jsがネイティブのfetch APIを拡張して、サーバー上の各リクエストが独自の永続的なキャッシュセマンティクスを設定できるようにしているためです。

知っておくと良いこと:ブラウザでは、fetchcacheオプションはリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示しますが、Next.jsでは、cacheオプションはサーバーサイドリクエストがサーバーのデータキャッシュとどのように相互作用するかを示します。

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

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

Diagram showing how cached and uncached fetch requests interact with the Data Cache. Cached requests are stored in the Data Cache, and memoized, uncached requests are fetched from the data source, not stored in the Data Cache, and memoized.
  • レンダリング中に'force-cache'オプションを指定したfetchリクエストが最初に呼び出されると、Next.jsはデータキャッシュにキャッシュされたレスポンスがないかを確認します。
  • キャッシュされたレスポンスが見つかった場合は、すぐに返され、メモ化されます。
  • キャッシュされたレスポンスが見つからない場合は、データソースにリクエストが行われ、結果がデータキャッシュに格納され、メモ化されます。
  • キャッシュされていないデータ(例えば、cacheオプションが定義されていない場合や、{ cache: 'no-store' }を使用している場合)については、結果は常にデータソースからフェッチされ、メモ化されます。
  • データがキャッシュされているかキャッシュされていないかに関わらず、リクエストは常にメモ化され、Reactレンダリングパス中に同じデータに対して重複したリクエストが行われることを回避します。

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

両方のキャッシュメカニズムはキャッシュされたデータを再利用することによりパフォーマンスを向上させるのに役立ちますが、データキャッシュは着信リクエストとデプロイメントにわたって永続的である一方、メモ化はリクエストのライフタイムの間だけ有効です。

期間

データキャッシュは、再検証またはオプトアウトしない限り、着信リクエストとデプロイメントにわたって永続的です。

再検証

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

  • 時間ベースの再検証:一定時間が経過し、新しいリクエストが行われた後、データを再検証します。これは、変更頻度が低く、鮮度がそれほど重要ではないデータに役立ちます。
  • オンデマンド再検証: イベント(例えば、フォーム送信)に基づいてデータを再検証します。オンデマンド再検証では、タグベースまたはパスベースのアプローチを使用して、データのグループを一度に再検証できます。これは、ヘッドレスCMSからのコンテンツが更新されたときなど、できるだけ早く最新のデータを表示したい場合に役立ちます。

時間ベースの再検証

一定の間隔でデータを再検証するには、fetchnext.revalidateオプションを使用して、リソースのキャッシュ有効期間(秒単位)を設定できます。

// Revalidate at most every hour
fetch('https://...', { next: { revalidate: 3600 } })

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

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

Diagram showing how time-based revalidation works, after the revalidation period, stale data is returned for the first request, then data is revalidated.
  • revalidateを指定したfetchリクエストが最初に呼び出されると、データは外部データソースからフェッチされ、データキャッシュに保存されます。
  • 指定された時間枠(例えば、60秒)内に呼び出されたリクエストは、キャッシュされたデータを返します。
  • 時間枠が過ぎると、次のリクエストはキャッシュされた(古くなった)データを返します。
    • Next.jsはバックグラウンドでデータの再検証をトリガーします。
    • データが正常にフェッチされると、Next.jsはデータキャッシュを最新データで更新します。
    • バックグラウンドの再検証が失敗した場合、以前のデータは変更されずに保持されます。

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

オンデマンド再検証

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

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

Diagram showing how on-demand revalidation works, the Data Cache is updated with fresh data after a revalidation request.
  • 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は、サーバーコンポーネントを、ストリーミング用に最適化された特別なデータ形式(React Server Component Payloadと呼ばれる)にレンダリングします。
  2. Next.jsは、React Server Component PayloadとクライアントコンポーネントのJavaScript命令を使用して、サーバーでHTMLをレンダリングします。

これは、作業をキャッシュしたり、応答を送信したりする前に、すべてがレンダリングされるのを待つ必要がないことを意味します。代わりに、作業が完了すると応答をストリーミングできます。

React Server Component Payloadとは何ですか?

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

  • サーバーコンポーネントのレンダリング結果
  • クライアントコンポーネントをレンダリングする必要がある場所のプレースホルダーと、そのJavaScriptファイルへの参照
  • サーバーコンポーネントからクライアントコンポーネントに渡されたプロパティ

詳細については、サーバーコンポーネントのドキュメントを参照してください。

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

Default behavior of the Full Route Cache, showing how the React Server Component Payload and HTML are cached on the server for statically rendered routes.

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

3. クライアントでの React ハイドレーションとリコンシリエーション

リクエスト時に、クライアント側で

  1. HTML は、クライアントおよびサーバーコンポーネントの高速でインタラクティブでない初期プレビューをすぐに表示するために使用されます。
  2. React Server Components Payload は、クライアントとレンダリングされたサーバーコンポーネントツリーをリコンシリエーションし、DOM を更新するために使用されます。
  3. JavaScript 命令は、クライアントコンポーネントをハイドレーションし、アプリケーションをインタラクティブにするために使用されます。

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

React Server Component Payload は、クライアント側のルーターキャッシュ (個々のルートセグメントで分割された個別のインメモリキャッシュ) に保存されます。このルーターキャッシュは、以前にアクセスしたルートを保存し、将来のルートをプリフェッチすることにより、ナビゲーションエクスペリエンスを向上させるために使用されます。

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

後続のナビゲーション中またはプリフェッチ中に、Next.js は React Server Components Payload がルーターキャッシュに保存されているかどうかを確認します。もしそうであれば、サーバーへの新しいリクエストの送信をスキップします。

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

静的レンダリングと動的レンダリング

ビルド時にルートがキャッシュされるかどうかは、静的にレンダリングされるか、動的にレンダリングされるかによって異なります。静的ルートはデフォルトでキャッシュされますが、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。

この図は、キャッシュされたデータとキャッシュされていないデータを使用した、静的にレンダリングされたルートと動的にレンダリングされたルートの違いを示しています。

How static and dynamic rendering affects the Full Route Cache. Static routes are cached at build time or after data revalidation, whereas dynamic routes are never cached

静的レンダリングと動的レンダリングについて詳しくはこちらをご覧ください。

期間

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

無効化

フルルートキャッシュを無効化するには、次の 2 つの方法があります。

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

オプトアウト

フルルートキャッシュをオプトアウトするか、言い換えれば、受信リクエストごとにコンポーネントを動的にレンダリングするには、次のいずれかの方法を使用します。

  • 動的 APIを使用する: これにより、ルートはフルルートキャッシュからオプトアウトされ、リクエスト時に動的にレンダリングされます。データキャッシュは引き続き使用できます。
  • dynamic = 'force-dynamic' または revalidate = 0 ルートセグメント構成オプションを使用する: これにより、フルルートキャッシュとデータキャッシュがスキップされます。つまり、コンポーネントがレンダリングされ、データはサーバーへの受信リクエストごとにフェッチされます。ルーターキャッシュはクライアント側のキャッシュであるため、引き続き適用されます。
  • データキャッシュをオプトアウトする: ルートにキャッシュされない fetch リクエストがある場合、これによりルートはフルルートキャッシュからオプトアウトされます。特定の fetch リクエストのデータは、受信リクエストごとにフェッチされます。キャッシュをオプトアウトしない他の fetch リクエストは、データキャッシュに引き続きキャッシュされます。これにより、キャッシュされたデータとキャッシュされていないデータのハイブリッドが可能になります。

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

Next.js には、レイアウト、ロード状態、およびページで分割されたルートセグメントの RSC ペイロードを保存する、インメモリのクライアント側ルーターキャッシュがあります。

ユーザーがルート間を移動すると、Next.js はアクセスしたルートセグメントをキャッシュし、ユーザーが移動する可能性のあるルートをプリフェッチします。これにより、瞬時の戻る/進むナビゲーション、ナビゲーション間のフルページリロードの回避、React 状態とブラウザー状態の保持が実現します。

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

  • レイアウトはキャッシュされ、ナビゲーション時に再利用されます (部分レンダリング)。
  • ロード状態はキャッシュされ、瞬時のナビゲーションのためにナビゲーション時に再利用されます。
  • ページはデフォルトではキャッシュされませんが、ブラウザーの戻る/進むナビゲーション中に再利用されます。実験的なstaleTimes構成オプションを使用すると、ページセグメントのキャッシュを有効にできます。

知っておくと便利です: このキャッシュは Next.js およびサーバーコンポーネントに特に関係し、ブラウザーのbfcacheとは異なりますが、同様の結果が得られます。

期間

キャッシュはブラウザーの一時メモリに保存されます。ルーターキャッシュが持続する時間は、次の 2 つの要因によって決まります。

  • セッション: キャッシュはナビゲーション全体で持続します。ただし、ページをリフレッシュするとクリアされます。
  • 自動無効化期間: レイアウトとロード状態のキャッシュは、特定の時間が経過すると自動的に無効化されます。期間は、リソースがプリフェッチされた方法と、リソースが静的に生成されたかどうかによって異なります。
    • デフォルトのプリフェッチ (prefetch={null} または指定なし): 動的ページではキャッシュされず、静的ページでは 5 分間キャッシュされます。
    • フルプリフェッチ (prefetch={true} または router.prefetch): 静的ページと動的ページの両方で 5 分間です。

ページをリフレッシュするとすべてのキャッシュされたセグメントがクリアされますが、自動無効化期間はプリフェッチされた時刻からの個々のセグメントにのみ影響します。

知っておくと便利です: 実験的な staleTimes 構成オプションを使用して、上記の自動無効化時間を調整できます。

無効化

ルーターキャッシュを無効化するには、次の 2 つの方法があります。

  • サーバーアクション
    • パス (revalidatePath) またはキャッシュタグ (revalidateTag) でオンデマンドでデータを再検証します。
    • cookies.set または cookies.delete を使用すると、Cookie を使用するルートが古くならないように (認証など)、ルーターキャッシュが無効化されます。
  • router.refresh を呼び出すと、ルーターキャッシュが無効になり、現在のルートに対してサーバーに新しいリクエストが行われます。

オプトアウト

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

知っておくと便利です: <Link> コンポーネントの prefetch プロパティを false に設定することで、プリフェッチをオプトアウトすることもできます。

キャッシュの相互作用

さまざまなキャッシュメカニズムを構成する際は、それらが相互にどのように作用するかを理解することが重要です。

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

  • データの再検証またはオプトアウトは、レンダリング出力がデータに依存するため、フルルートキャッシュを無効にします
  • フルルートキャッシュの無効化またはオプトアウトは、データキャッシュには影響しません。キャッシュされたデータとキャッシュされていないデータの両方を持つルートを動的にレンダリングできます。これは、ページの大部分でキャッシュされたデータを使用するが、リクエスト時にフェッチする必要があるデータに依存するコンポーネントがいくつかある場合に役立ちます。すべてのデータを再フェッチすることによるパフォーマンスへの影響を心配することなく、動的にレンダリングできます。

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

  • データキャッシュとルーターキャッシュを直ちに無効化するには、revalidatePathまたはrevalidateTagサーバーアクションで使用できます。
  • ルートハンドラーでデータキャッシュを再検証しても、ルートハンドラーは特定のルートに関連付けられていないため、ルーターキャッシュは直ちに無効化されません。これは、ハードリフレッシュまたは自動無効化期間が経過するまで、ルーターキャッシュが以前のペイロードを提供し続けることを意味します。

API

次の表は、異なる Next.js API がキャッシュにどのように影響するかについての概要を示します。

APIルーターキャッシュフルルートキャッシュデータキャッシュReact キャッシュ
<Link prefetch>キャッシュ
router.prefetchキャッシュ
router.refresh再検証
fetchキャッシュキャッシュ
fetch options.cacheキャッシュまたはオプトアウト
fetch options.next.revalidate再検証再検証
fetch options.next.tagsキャッシュキャッシュ
revalidateTag再検証(サーバーアクション)再検証再検証
revalidatePath再検証(サーバーアクション)再検証再検証
const revalidate再検証またはオプトアウト再検証またはオプトアウト
const dynamicキャッシュまたはオプトアウトキャッシュまたはオプトアウト
cookies再検証(サーバーアクション)オプトアウト
headerssearchParamsオプトアウト
generateStaticParamsキャッシュ
React.cacheキャッシュ
unstable_cacheキャッシュ

デフォルトでは、<Link>コンポーネントはフルルートキャッシュからルートを自動的にプリフェッチし、Reactサーバーコンポーネントのペイロードをルーターキャッシュに追加します。

プリフェッチを無効にするには、prefetchプロパティをfalseに設定できます。ただし、これによりキャッシュが永続的にスキップされるわけではなく、ユーザーがルートにアクセスしたときに、ルートセグメントはクライアント側でキャッシュされます。

<Link>コンポーネントの詳細をご覧ください。

router.prefetch

useRouterフックのprefetchオプションを使用して、ルートを手動でプリフェッチできます。これにより、Reactサーバーコンポーネントのペイロードがルーターキャッシュに追加されます。

useRouterフックのAPIリファレンスをご覧ください。

router.refresh

useRouterフックのrefreshオプションを使用して、ルートを手動で更新できます。これにより、ルーターキャッシュが完全にクリアされ、現在のルートに対する新しいリクエストがサーバーに送信されます。refreshは、データキャッシュまたはフルルートキャッシュには影響しません。

レンダリングされた結果は、Reactの状態とブラウザの状態を保持しながら、クライアント上で調整されます。

useRouterフックのAPIリファレンスをご覧ください。

fetch

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

fetchからのレスポンスをキャッシュしたくない場合は、次のようにすることができます。

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

詳細なオプションについては、fetch APIリファレンスをご覧ください。

fetch options.cache

cacheオプションをforce-cacheに設定することで、個々のfetchをキャッシュにオプトインできます。

// Opt into caching
fetch(`https://...`, { cache: 'force-cache' })

詳細なオプションについては、fetch APIリファレンスをご覧ください。

fetch options.next.revalidate

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

// Revalidate at most after 1 hour
fetch(`https://...`, { next: { revalidate: 3600 } })

詳細なオプションについては、fetch APIリファレンスをご覧ください。

fetch options.next.tagsrevalidateTag

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

  1. fetchまたはunstable_cacheを使用する場合、1つまたは複数のタグでキャッシュエントリにタグ付けするオプションがあります。
  2. 次に、revalidateTagを呼び出して、そのタグに関連付けられたキャッシュエントリをパージできます。

たとえば、データをフェッチするときにタグを設定できます。

// Cache data with a tag
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })

次に、revalidateTagをタグとともに呼び出して、キャッシュエントリをパージします。

// Revalidate entries with a specific tag
revalidateTag('a')

達成しようとしている内容に応じて、revalidateTagを使用できる場所は2つあります。

  1. ルートハンドラー - サードパーティのイベント(例:webhook)に応じてデータを再検証するため。ルートハンドラーは特定のルートに関連付けられていないため、ルーターキャッシュは直ちに無効化されません。
  2. サーバーアクション - ユーザーアクション(例:フォームの送信)後にデータを再検証するため。これにより、関連付けられたルートのルーターキャッシュが無効化されます。

revalidatePath

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

revalidatePath('/')

達成しようとしている内容に応じて、revalidatePathを使用できる場所は2つあります。

  1. ルートハンドラー - サードパーティのイベント(例:webhook)に応じてデータを再検証するため。
  2. サーバーアクション - ユーザーインタラクション(例:フォームの送信、ボタンのクリック)後にデータを再検証するため。

詳細については、revalidatePath APIリファレンスをご覧ください。

revalidatePath vs. router.refresh

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

違いは、revalidatePathがデータキャッシュとフルルートキャッシュをパージするのに対し、router.refresh()はクライアント側のAPIであるため、データキャッシュとフルルートキャッシュを変更しないことです。

動的API

cookiesheadersなどの動的API、およびページ内のsearchParamsプロパティは、ランタイムの着信リクエスト情報に依存します。これらを使用すると、ルートがフルルートキャッシュからオプトアウトされます。言い換えれば、ルートは動的にレンダリングされます。

cookies

サーバーアクションでcookies.setまたはcookies.deleteを使用すると、クッキーを使用するルートが古くなるのを防ぐために、ルーターキャッシュが無効化されます(例:認証の変更を反映するため)。

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())
 
  // Render the first 10 posts at build time
  return posts.slice(0, 10).map((post) => ({
    slug: post.slug,
  }))
}

最初にアクセスされたときにすべてのパスを静的にレンダリングするには、空の配列を返す(ビルド時にパスはレンダリングされない)か、export const dynamic = 'force-static'を利用します。

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

知っておくと良いこと: generateStaticParamsからは、空の場合でも、配列を返す必要があります。そうしないと、ルートは動的にレンダリングされます。

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

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

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
})