Next.jsにおけるキャッシュ
Next.jsは、レンダリング作業とデータリクエストをキャッシュすることで、アプリケーションのパフォーマンスを向上させ、コストを削減します。このページでは、Next.jsのキャッシュメカニズム、それらを設定するために使用できるAPI、およびそれらが相互にどのように作用するかについて詳しく説明します。
知っておくと良いこと: このページはNext.jsの内部動作を理解するのに役立ちますが、Next.jsを生産的に使用するために必須の知識ではありません。Next.jsのキャッシュヒューリスティックのほとんどは、APIの使用状況によって決定され、ゼロまたは最小限の設定で最高のパフォーマンスを得られるデフォルト値が設定されています。
概要
以下は、さまざまなキャッシュメカニズムとその目的の概要です:
メカニズム | 対象 | 場所 | 目的 | 期間 |
---|---|---|---|---|
リクエストメモ化 | 関数の戻り値 | サーバー | Reactコンポーネントツリー内でデータを再利用 | リクエストライフサイクル中 |
データキャッシュ | データ | サーバー | ユーザーリクエストとデプロイメント間でデータを保存 | 永続的(再検証可能) |
フルルートキャッシュ | HTMLとRSCペイロード | サーバー | レンダリングコストを削減しパフォーマンスを向上 | 永続的(再検証可能) |
ルーターキャッシュ | RSCペイロード | クライアント | ナビゲーション時のサーバーリクエストを削減 | ユーザーセッションまたは時間ベース |
デフォルトでは、Next.jsはパフォーマンスを向上させ、コストを削減するために可能な限りキャッシュします。つまり、明示的にオプトアウトしない限り、ルートは静的にレンダリングされ、データリクエストはキャッシュされます。下の図は、ビルド時にルートが静的にレンダリングされ、静的ルートが初めて訪問されたときのデフォルトのキャッシュ動作を示しています。

キャッシュ動作は、ルートが静的にレンダリングされるか動的にレンダリングされるか、データがキャッシュされるかされないか、リクエストが初回訪問か後続のナビゲーションの一部かによって変化します。ユースケースに応じて、個々のルートとデータリクエストのキャッシュ動作を設定できます。
リクエストメモ化
Reactはfetch
APIを拡張して、同じURLとオプションを持つリクエストを自動的にメモ化します。これは、Reactコンポーネントツリー内の複数の場所で同じデータに対してfetch関数を呼び出しても、実際には一度だけ実行されることを意味します。

例えば、ルート全体(レイアウト、ページ、複数のコンポーネントなど)で同じデータを使用する必要がある場合、ツリーの上部でデータを取得してからコンポーネント間でpropsを転送する必要はありません。代わりに、データが必要なコンポーネントでデータを取得でき、同じデータに対してネットワーク経由で複数のリクエストを行うパフォーマンスへの影響を心配する必要はありません。
async function getItem() {
// `fetch`関数は自動的にメモ化され、結果がキャッシュされます
const res = await fetch('https://.../item/1')
return res.json()
}
// この関数は2回呼び出されますが、最初の1回だけ実行されます
const item = await getItem() // キャッシュMISS
// 2回目の呼び出しはルート内のどこでも可能
const item = await getItem() // キャッシュHIT
async function getItem() {
// `fetch`関数は自動的にメモ化され、結果がキャッシュされます
const res = await fetch('https://.../item/1')
return res.json()
}
// この関数は2回呼び出されますが、最初の1回だけ実行されます
const item = await getItem() // キャッシュMISS
// 2回目の呼び出しはルート内のどこでも可能
const item = await getItem() // キャッシュHIT
リクエストメモ化の仕組み

- ルートのレンダリング中、特定のリクエストが初めて呼び出されると、その結果はメモリに存在せず、キャッシュ
MISS
になります。 - したがって、関数が実行され、外部ソースからデータが取得され、結果がメモリに保存されます。
- 同じレンダリングパス内でのリクエストの後続の関数呼び出しはキャッシュ
HIT
になり、関数を実行せずにメモリからデータが返されます。 - ルートのレンダリングが完了し、レンダリングパスが終了すると、メモリが「リセット」され、すべてのリクエストメモ化エントリがクリアされます。
知っておくと良いこと:
- リクエストメモ化はNext.jsの機能ではなく、Reactの機能です。他のキャッシュメカニズムとの相互作用を示すためにここに含まれています。
- メモ化は
fetch
リクエストのGET
メソッドにのみ適用されます。- メモ化はReactコンポーネントツリーにのみ適用されます。つまり:
generateMetadata
、generateStaticParams
、レイアウト、ページ、およびその他のサーバーコンポーネント内のfetch
リクエストに適用されます。- ルートハンドラー内の
fetch
リクエストには適用されません。これらはReactコンポーネントツリーの一部ではないためです。fetch
が適さない場合(一部のデータベースクライアント、CMSクライアント、GraphQLクライアントなど)、Reactのcache
関数を使用して関数をメモ化できます。
期間
キャッシュは、サーバーリクエストのライフタイム中、Reactコンポーネントツリーのレンダリングが完了するまで続きます。
再検証
メモ化はサーバーリクエスト間で共有されず、レンダリング中にのみ適用されるため、再検証する必要はありません。
オプトアウト
fetch
リクエストのメモ化をオプトアウトするには、AbortController
のsignal
をリクエストに渡します。
const { signal } = new AbortController()
fetch(url, { signal })
データキャッシュ
Next.jsには、データ取得の結果を永続化する組み込みのデータキャッシュがあり、サーバーリクエストとデプロイメント間で保持されます。これは、Next.jsがネイティブのfetch
APIを拡張して、サーバー上の各リクエストが独自の永続的なキャッシュセマンティクスを設定できるようにするためです。
知っておくと良いこと: ブラウザでは、
fetch
のcache
オプションはリクエストがブラウザのHTTPキャッシュとどのように相互作用するかを示しますが、Next.jsでは、cache
オプションはサーバーサイドリクエストがサーバーのデータキャッシュとどのように相互作用するかを示します。
デフォルトでは、fetch
を使用するデータリクエストはキャッシュされます。fetch
のcache
およびnext.revalidate
オプションを使用して、キャッシュ動作を設定できます。
データキャッシュの仕組み

- レンダリング中に
fetch
リクエストが初めて呼び出されると、Next.jsはデータキャッシュでキャッシュされたレスポンスを確認します。 - キャッシュされたレスポンスが見つかった場合、即座に返され、メモ化されます。
- キャッシュされたレスポンスが見つからない場合、データソースにリクエストが行われ、結果がデータキャッシュに保存され、メモ化されます。
- キャッシュされていないデータ(例:
{ cache: 'no-store' }
)の場合、結果は常にデータソースから取得され、メモ化されます。 - データがキャッシュされているかどうかに関係なく、リクエストは常にメモ化され、Reactレンダリングパス中に同じデータに対して重複したリクエストが行われないようにします。
データキャッシュとリクエストメモ化の違い
どちらのキャッシュメカニズムもキャッシュされたデータを再利用することでパフォーマンスを向上させますが、データキャッシュは受信リクエストとデプロイメント間で永続的であるのに対し、メモ化はリクエストのライフタイム中のみ有効です。
メモ化により、レンダリングサーバーからデータキャッシュサーバー(CDNやエッジネットワークなど)またはデータソース(データベースやCMSなど)へのネットワーク境界を越える必要がある同じレンダリングパス内の重複リクエストの数を減らします。データキャッシュにより、オリジンデータソースへのリクエスト数を減らします。
期間
データキャッシュは、再検証またはオプトアウトしない限り、受信リクエストとデプロイメント間で永続的です。
再検証
キャッシュされたデータは、次の2つの方法で再検証できます:
- 時間ベースの再検証: 一定時間が経過し、新しいリクエストが行われた後にデータを再検証します。これは、変更頻度が低く、鮮度がそれほど重要でないデータに役立ちます。
- オンデマンド再検証: イベント(フォーム送信など)に基づいてデータを再検証します。オンデマンド再検証では、タグベースまたはパスベースのアプローチを使用して、一度にデータのグループを再検証できます。これは、できるだけ早く最新のデータを表示したい場合(ヘッドレスCMSからのコンテンツが更新されたときなど)に役立ちます。
時間ベースの再検証
一定間隔でデータを再検証するには、fetch
のnext.revalidate
オプションを使用してリソースのキャッシュ寿命(秒単位)を設定します。
// 最大1時間ごとに再検証
fetch('https://...', { next: { revalidate: 3600 } })
または、ルートセグメント設定オプションを使用して、セグメント内のすべてのfetch
リクエストを設定したり、fetch
を使用できない場合に設定したりできます。
時間ベースの再検証の仕組み

revalidate
を指定したfetchリクエストが初めて呼び出されると、外部データソースからデータが取得され、データキャッシュに保存されます。- 指定された時間枠内(例:60秒)に呼び出されたリクエストはすべて、キャッシュされたデータを返します。
- 時間枠が過ぎると、次のリクエストでもキャッシュされた(古くなった)データが返されます。
- Next.jsはバックグラウンドでデータの再検証をトリガーします。
- データが正常に取得されると、Next.jsはデータキャッシュを新しいデータで更新します。
- バックグラウンドの再検証が失敗した場合、以前のデータは変更されずに保持されます。
これはstale-while-revalidateの動作に似ています。
オンデマンド再検証
データは、パス(revalidatePath
)またはキャッシュタグ(revalidateTag
)によってオンデマンドで再検証できます。
オンデマンド再検証の仕組み

fetch
リクエストが初めて呼び出されると、外部データソースからデータが取得され、データキャッシュに保存されます。- オンデマンド再検証がトリガーされると、適切なキャッシュエントリがキャッシュから削除されます。
- これは、新しいデータが取得されるまで古いデータをキャッシュに保持する時間ベースの再検証とは異なります。
- 次にリクエストが行われると、再びキャッシュ
MISS
になり、外部データソースからデータが取得され、データキャッシュに保存されます。
オプトアウト
個々のデータ取得では、cache
オプションをno-store
に設定することでキャッシュをオプトアウトできます。これにより、fetch
が呼び出されるたびにデータが取得されます。
// 個々の`fetch`リクエストのキャッシュをオプトアウト
fetch(`https://...`, { cache: 'no-store' })
または、ルートセグメント設定オプションを使用して、特定のルートセグメントのキャッシュをオプトアウトすることもできます。これにより、サードパーティライブラリを含むルートセグメント内のすべてのデータリクエストが影響を受けます。
// ルートセグメント内のすべてのデータリクエストのキャッシュをオプトアウト
export const dynamic = 'force-dynamic'
Vercelデータキャッシュ
Next.jsアプリケーションがVercelにデプロイされている場合は、Vercel固有の機能をよりよく理解するためにVercelデータキャッシュドキュメントを読むことをお勧めします。
フルルートキャッシュ
関連用語:
自動静的最適化、静的サイト生成、または静的レンダリングという用語が、ビルド時にアプリケーションのルートをレンダリングしてキャッシュするプロセスを指すために互換的に使用されているのを見かけることがあります。
Next.jsはビルド時にルートを自動的にレンダリングしてキャッシュします。これは、サーバーで毎回レンダリングする代わりにキャッシュされたルートを提供できるようにする最適化であり、ページの読み込みが速くなります。
フルルートキャッシュの動作を理解するには、Reactがレンダリングをどのように処理するか、およびNext.jsが結果をどのようにキャッシュするかを見ることが役立ちます:
1. サーバー上のReactレンダリング
サーバー上では、Next.jsはReactのAPIを使用してレンダリングを調整します。レンダリング作業は、個々のルートセグメントとSuspense境界によってチャンクに分割されます。
各チャンクは2つのステップでレンダリングされます:
- Reactはサーバーコンポーネントを、ストリーミング用に最適化された特別なデータ形式であるReact Server Component Payloadにレンダリングします。
- Next.jsはReact Server Component PayloadとクライアントコンポーネントのJavaScript命令を使用して、サーバー上でHTMLをレンダリングします。
これは、作業をキャッシュしたりレスポンスを送信したりする前に、すべてがレンダリングされるのを待つ必要がないことを意味します。代わりに、作業が完了するとレスポンスをストリーミングできます。
React Server Component Payloadとは何ですか?
React Server Component Payloadは、レンダリングされたReactサーバーコンポーネントツリーのコンパクトなバイナリ表現です。クライアント上のReactがブラウザのDOMを更新するために使用します。React Server Component Payloadには以下が含まれます:
- サーバーコンポーネントのレンダリング結果
- クライアントコンポーネントをレンダリングする場所のプレースホルダーとそれらのJavaScriptファイルへの参照
- サーバーコンポーネントからクライアントコンポーネントに渡されるprops
詳細は、サーバーコンポーネントドキュメントを参照してください。
2. サーバー上のNext.jsキャッシュ(フルルートキャッシュ)

Next.jsのデフォルトの動作は、ルートのレンダリング結果(React Server Component PayloadとHTML)をサーバー上でキャッシュすることです。これは、ビルド時に静的にレンダリングされたルート、または再検証中に適用されます。
3. クライアント上のReactハイドレーションと調整
リクエスト時に、クライアント上で:
- HTMLは、クライアントとサーバーコンポーネントの高速で非インタラクティブな初期プレビューをすぐに表示するために使用されます。
- React Server Components Payloadは、クライアントとレンダリングされたサーバーコンポーネントツリーを調整し、DOMを更新するために使用されます。
- JavaScript命令は、クライアントコンポーネントをハイドレートし、アプリケーションをインタラクティブにするために使用されます。
4. クライアント上のNext.jsキャッシュ(ルーターキャッシュ)
React Server Component Payloadは、クライアントサイドのルーターキャッシュに保存されます。これは個々のルートセグメントごとに分割されたメモリ内キャッシュです。このルーターキャッシュは、以前に訪問したルートを保存し、将来のルートをプリフェッチすることで、ナビゲーションエクスペリエンスを向上させるために使用されます。
5. 後続のナビゲーション
後続のナビゲーションまたはプリフェッチ中、Next.jsはReactサーバーコンポーネントのペイロードがルーターキャッシュに保存されているか確認します。存在する場合、サーバーへの新しいリクエストの送信をスキップします。
ルートセグメントがキャッシュに存在しない場合、Next.jsはサーバーからReactサーバーコンポーネントのペイロードを取得し、クライアント側のルーターキャッシュを更新します。
静的および動的レンダリング
ビルド時にルートがキャッシュされるかどうかは、静的レンダリングか動的レンダリングかによって決まります。静的ルートはデフォルトでキャッシュされますが、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。
この図は、静的および動的レンダリングされたルートの違いと、キャッシュされたデータとキャッシュされていないデータを示しています:

静的および動的レンダリングについて詳しく学ぶ。
期間
デフォルトでは、フルルートキャッシュは永続的です。つまり、レンダリング出力はユーザーリクエスト間でキャッシュされます。
無効化
フルルートキャッシュを無効化する方法は2つあります:
- データの再検証: データキャッシュを再検証すると、サーバー上でコンポーネントを再レンダリングし、新しいレンダリング出力をキャッシュすることで、ルーターキャッシュも無効化されます。
- 再デプロイ: デプロイ間で永続化されるデータキャッシュとは異なり、フルルートキャッシュは新しいデプロイ時にクリアされます。
オプトアウト
以下の方法でフルルートキャッシュをオプトアウト(つまり、毎回の受信リクエストに対してコンポーネントを動的にレンダリング)できます:
- 動的関数の使用: これによりルートはフルルートキャッシュから除外され、リクエスト時に動的にレンダリングされます。データキャッシュは引き続き使用可能です。
dynamic = 'force-dynamic'
またはrevalidate = 0
ルートセグメント設定オプションの使用: これによりフルルートキャッシュとデータキャッシュがスキップされます。つまり、コンポーネントはサーバーへの毎回の受信リクエストごとにレンダリングされ、データが取得されます。ルーターキャッシュはクライアント側キャッシュとして引き続き適用されます。- データキャッシュのオプトアウト: ルートにキャッシュされていない
fetch
リクエストがある場合、そのルートはフルルートキャッシュから除外されます。特定のfetch
リクエストのデータは、毎回の受信リクエストごとに取得されます。キャッシュをオプトアウトしない他のfetch
リクエストは、データキャッシュに引き続きキャッシュされます。これにより、キャッシュされたデータとキャッシュされていないデータのハイブリッドが可能になります。
ルーターキャッシュ
関連用語:
ルーターキャッシュはクライアントサイドキャッシュまたはプリフェッチキャッシュと呼ばれることがあります。プリフェッチキャッシュはプリフェッチされたルートセグメントを指し、クライアントサイドキャッシュは訪問済みとプリフェッチされたセグメントの両方を含むルーターキャッシュ全体を指します。 このキャッシュはNext.jsとサーバーコンポーネントに固有のものであり、ブラウザのbfcacheとは異なりますが、同様の結果をもたらします。
Next.jsには、ユーザーセッション期間中、Reactサーバーコンポーネントのペイロードを個々のルートセグメントごとに分割して保存するインメモリのクライアントサイドキャッシュがあります。これをルーターキャッシュと呼びます。
ルーターキャッシュの仕組み

ユーザーがルート間を移動すると、Next.jsは訪問済みのルートセグメントをキャッシュし、ユーザーが移動する可能性の高いルート(ビューポート内の<Link>
コンポーネントに基づく)をプリフェッチします。
これにより、ユーザーにとって以下のようなナビゲーション体験が向上します:
- 訪問済みルートがキャッシュされているため、前後への即時ナビゲーションが可能。プリフェッチと部分レンダリングにより、新しいルートへの高速ナビゲーションが実現。
- ナビゲーション間のフルページリロードが不要で、Reactの状態とブラウザの状態が保持されます。
ルーターキャッシュとフルルートキャッシュの違い:
ルーターキャッシュはReactサーバーコンポーネントのペイロードをブラウザの一時メモリにユーザーセッション期間中保存しますが、フルルートキャッシュはReactサーバーコンポーネントのペイロードとHTMLをサーバー上で複数のユーザーリクエストにわたって永続的に保存します。
フルルートキャッシュは静的にレンダリングされたルートのみをキャッシュしますが、ルーターキャッシュは静的および動的にレンダリングされたルートの両方に適用されます。
期間
キャッシュはブラウザの一時メモリに保存されます。ルーターキャッシュの持続時間は2つの要素で決まります:
- セッション: キャッシュはナビゲーション間で保持されます。ただし、ページのリフレッシュでクリアされます。
- 自動無効化期間: 個々のセグメントのキャッシュは、特定の時間後に自動的に無効化されます。期間はルートが静的または動的にレンダリングされるかによって異なります:
- 動的レンダリング: 30秒
- 静的レンダリング: 5分
ページリフレッシュはすべてのキャッシュされたセグメントをクリアしますが、自動無効化期間は個々のセグメントが最後にアクセスまたは作成された時点からのみ影響します。
動的にレンダリングされたルートに対してprefetch={true}
を追加するかrouter.prefetch
を呼び出すことで、5分間のキャッシュを選択できます。
無効化
ルーターキャッシュを無効化する方法は2つあります:
- サーバーアクション内で:
- パス指定でオンデマンドにデータを再検証する(
revalidatePath
)またはキャッシュタグ指定で再検証する(revalidateTag
) cookies.set
またはcookies.delete
を使用すると、ルーターキャッシュが無効化され、クッキーを使用するルート(例:認証)が古くなるのを防ぎます。
- パス指定でオンデマンドにデータを再検証する(
router.refresh
を呼び出すと、ルーターキャッシュが無効化され、現在のルートに対してサーバーに新しいリクエストが行われます。
オプトアウト
ルーターキャッシュをオプトアウトすることはできません。
<Link>
コンポーネントのprefetch
プロパティをfalse
に設定することでプリフェッチをオプトアウトできます。ただし、これでもタブバーや前後ナビゲーションなどのネストされたセグメント間の即時ナビゲーションを可能にするため、ルートセグメントが30秒間一時的に保存されます。訪問済みルートは引き続きキャッシュされます。
キャッシュの相互作用
異なるキャッシュメカニズムを設定する際には、それらがどのように相互作用するかを理解することが重要です:
データキャッシュとフルルートキャッシュ
- データキャッシュの再検証またはオプトアウトは、レンダリング出力がデータに依存するため、フルルートキャッシュを無効化します。
- フルルートキャッシュの無効化またはオプトアウトは、データキャッシュに影響しません。キャッシュされたデータとキャッシュされていないデータの両方を持つルートを動的にレンダリングできます。これは、ページの大部分がキャッシュされたデータを使用しているが、リクエスト時に取得する必要があるデータに依存する少数のコンポーネントがある場合に便利です。すべてのデータを再取得するパフォーマンスへの影響を心配することなく、動的にレンダリングできます。
データキャッシュとクライアントサイドルーターキャッシュ
- ルートハンドラーでデータキャッシュを再検証しても、ルートハンドラーが特定のルートに関連付けられていないため、ルーターキャッシュはすぐには無効化されません。つまり、ハードリフレッシュまたは自動無効化期間が経過するまで、ルーターキャッシュは以前のペイロードを提供し続けます。
- データキャッシュとルーターキャッシュを即座に無効化するには、サーバーアクションで
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 | 再検証(サーバーアクション) | オプトアウト | ||
headers , useSearchParams , searchParams | オプトアウト | |||
generateStaticParams | キャッシュ | |||
React.cache | キャッシュ | |||
unstable_cache (近日公開) |
<Link>
デフォルトでは、<Link>
コンポーネントはフルルートキャッシュからルートを自動的にプリフェッチし、Reactサーバーコンポーネントのペイロードをルーターキャッシュに追加します。
プリフェッチを無効にするには、prefetch
プロパティをfalse
に設定できます。ただし、これでもユーザーがルートを訪問したときにルートセグメントはクライアントサイドでキャッシュされます。
<Link>
コンポーネントについて詳しく学ぶ。
router.prefetch
useRouter
フックのprefetch
オプションを使用して、手動でルートをプリフェッチできます。これにより、Reactサーバーコンポーネントのペイロードがルーターキャッシュに追加されます。
useRouter
フックのAPIリファレンスを参照。
router.refresh
useRouter
フックのrefresh
オプションを使用して、手動でルートをリフレッシュできます。これによりルーターキャッシュが完全にクリアされ、現在のルートに対してサーバーに新しいリクエストが行われます。refresh
はデータキャッシュやフルルートキャッシュには影響しません。
レンダリング結果は、Reactの状態とブラウザの状態を保持しながらクライアント側で調整されます。
useRouter
フックのAPIリファレンスを参照。
fetch
fetch
から返されるデータは自動的にデータキャッシュに保存されます。
// デフォルトでキャッシュ。`force-cache`はデフォルトオプションで省略可能。
fetch(`https://...`, { cache: 'force-cache' })
その他のオプションについてはfetch
APIリファレンスを参照。
fetch options.cache
cache
オプションをno-store
に設定することで、個々のfetch
リクエストをデータキャッシュから除外できます:
// キャッシュをオプトアウト
fetch(`https://...`, { cache: 'no-store' })
レンダリング出力がデータに依存するため、cache: 'no-store'
を使用すると、fetch
リクエストが使用されているルートのフルルートキャッシュもスキップされます。つまり、ルートは毎回のリクエストで動的にレンダリングされますが、同じルート内で他のキャッシュされたデータリクエストを持つことができます。
その他のオプションについてはfetch
APIリファレンスを参照。
fetch options.next.revalidate
fetch
のnext.revalidate
オプションを使用して、個々のfetch
リクエストの再検証期間(秒単位)を設定できます。これによりデータキャッシュが再検証され、フルルートキャッシュも再検証されます。新しいデータが取得され、コンポーネントがサーバー上で再レンダリングされます。
// 最大1時間ごとに再検証
fetch(`https://...`, { next: { revalidate: 3600 } })
その他のオプションについてはfetch
APIリファレンスを参照。
fetch options.next.tags
とrevalidateTag
Next.jsには、きめ細かいデータキャッシュと再検証のためのキャッシュタグシステムがあります。
fetch
またはunstable_cache
を使用する際、キャッシュエントリに1つ以上のタグを付けることができます。- その後、
revalidateTag
を呼び出して、そのタグに関連付けられたキャッシュエントリを削除できます。
例えば、データ取得時にタグを設定できます:
// タグ付きでデータをキャッシュ
fetch(`https://...`, { next: { tags: ['a', 'b', 'c'] } })
そして、タグを指定してrevalidateTag
を呼び出し、キャッシュエントリを削除します:
// 特定のタグを持つエントリを再検証
revalidateTag('a')
revalidateTag
は、達成したい目的に応じて2つの場所で使用できます:
- ルートハンドラー - サードパーティのイベント(例:ウェブフック)に応じてデータを再検証。ルートハンドラーは特定のルートに関連付けられていないため、ルーターキャッシュはすぐには無効化されません。
- サーバーアクション - ユーザーアクション(例:フォーム送信)後にデータを再検証。これにより関連するルートのルーターキャッシュが無効化されます。
revalidatePath
revalidatePath
を使用すると、特定のパス以下のルートセグメントのデータを手動で再検証し、再レンダリングすることができます。revalidatePath
を呼び出すと、データキャッシュ (Data Cache) が再検証され、それによってフルルートキャッシュ (Full Route Cache) が無効化されます。
revalidatePath('/')
revalidatePath
は、目的に応じて次の2つの場所で使用できます:
- ルートハンドラー (Route Handlers) - サードパーティのイベント(例: Webhook)に応じてデータを再検証する場合
- サーバーアクション (Server Actions) - ユーザー操作(例: フォーム送信、ボタンクリック)後にデータを再検証する場合
詳細については、revalidatePath
APIリファレンスを参照してください。
revalidatePath
とrouter.refresh
の違い:
router.refresh
を呼び出すと、ルーターキャッシュ (Router Cache) がクリアされ、サーバー上でルートセグメントが再レンダリングされますが、データキャッシュ (Data Cache) やフルルートキャッシュ (Full Route Cache) は無効化されません。主な違いは、
revalidatePath
がデータキャッシュとフルルートキャッシュを消去するのに対し、router.refresh()
はクライアントサイドAPIであるため、データキャッシュとフルルートキャッシュを変更しない点です。
動的関数 (Dynamic Functions)
cookies
、headers
、useSearchParams
、searchParams
はすべて、実行時のリクエスト情報に依存する動的関数です。これらを使用すると、ルートがフルルートキャッシュから除外され、動的にレンダリングされます。
cookies
サーバーアクション内でcookies.set
またはcookies.delete
を使用すると、ルーターキャッシュ (Router Cache) が無効化され、クッキーを使用するルートが古くなるのを防ぎます(例: 認証状態の変更を反映)。
詳細は、cookies
APIリファレンスを参照してください。
セグメント設定オプション (Segment Config Options)
ルートセグメント設定オプションは、ルートセグメントのデフォルトを上書きする場合や、fetch
APIが使用できない場合(例: データベースクライアントやサードパーティライブラリ)に使用できます。
以下のルートセグメント設定オプションを使用すると、データキャッシュとフルルートキャッシュから除外されます:
const dynamic = 'force-dynamic'
const revalidate = 0
その他のオプションについては、ルートセグメント設定 (Route Segment Config) ドキュメントを参照してください。
generateStaticParams
動的セグメント (dynamic segments)(例: app/blog/[slug]/page.js
)の場合、generateStaticParams
で提供されたパスはビルド時にフルルートキャッシュに保存されます。リクエスト時には、ビルド時には知られていなかったパスも初回アクセス時にキャッシュされます。
ルートセグメントでexport const dynamicParams = false
オプションを使用すると、リクエスト時のキャッシュを無効化できます。この設定を使用すると、generateStaticParams
で提供されたパスのみが提供され、他のルートは404になるか、(キャッチオールルート (catch-all routes)の場合)マッチします。
詳細は、generateStaticParams
APIリファレンスを参照してください。
React cache
関数
Reactのcache
関数を使用すると、関数の戻り値をメモ化でき、同じ関数を複数回呼び出しても一度だけ実行されます。
fetch
リクエストは自動的にメモ化されるため、Reactのcache
でラップする必要はありません。ただし、fetch
APIが適さない場合(例: データベースクライアント、CMSクライアント、GraphQLクライアントなど)に、データリクエストを手動でメモ化するために使用できます。
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
})
import { cache } from 'react'
import db from '@/lib/db'
export const getItem = cache(async (id) => {
const item = await db.item.findUnique({ id })
return item
})
unstable_cache
unstable_cache
は、fetch
APIが適さない場合(例: データベースクライアント、CMSクライアント、GraphQLなど)にデータキャッシュに値を追加するための実験的APIです。
import { unstable_cache } from 'next/cache'
export default async function Page() {
const cachedData = await unstable_cache(
async () => {
const data = await db.query('...')
return data
},
['cache-key'],
{
tags: ['a', 'b', 'c'],
revalidate: 10,
}
)()
}
警告: このAPIは開発中であり、本番環境での使用は推奨されません。データキャッシュの将来の方向性を示すために記載されています。