Next.jsのキャッシュ
Next.jsは、レンダリング作業やデータリクエストをキャッシュすることで、アプリケーションのパフォーマンスを向上させ、コストを削減します。このページでは、Next.jsのキャッシュメカニズム、設定に使用できるAPI、およびそれらがどのように相互作用するかについて詳しく説明します。
知っておくとよいこと: このページは、Next.jsがどのように動作するかを理解するのに役立ちますが、Next.jsで生産的に作業するための必須知識ではありません。ほとんどのNext.jsのキャッシュヒューリスティックスは、APIの使用によって決定され、ゼロまたは最小限の設定で最高のパフォーマンスを実現するためのデフォルトが用意されています。代わりに例を参照したい場合は、こちらから始めてください。
概要
以下は、さまざまなキャッシュメカニズムとその目的の概要です:
メカニズム | 何 | 場所 | 目的 | 期間 |
---|---|---|---|---|
Request Memoization | 関数の戻り値 | サーバー | React Component treeでのデータ再利用 | リクエストライフサイクル中 |
Data Cache | データ | サーバー | ユーザーリクエストとデプロイ間でのデータ保存 | 永続的(再検証可能) |
Full Route Cache | HTMLとRSCペイロード | サーバー | レンダリングコストの削減とパフォーマンス向上 | 永続的(再検証可能) |
Router Cache | RSCペイロード | クライアント | ナビゲーション時のサーバーリクエスト削減 | ユーザーセッションまたは時間ベース |
デフォルトでは、Next.jsはパフォーマンスを向上させ、コストを削減するために可能な限り多くのキャッシュを行います。つまり、ルートは静的にレンダリングされ、データリクエストはキャッシュされます(オプトアウトしない限り)。次の図は、ビルド時および静的ルートが最初に訪問されたときにルートが静的にレンダリングされる様子を示しています。
キャッシュ動作は、ルートが静的または動的にレンダリングされるか、データがキャッシュされるかされないか、リクエストが初回訪問またはその後のナビゲーションの一部であるかによって変わります。利用ケースに応じて個々のルートとデータリクエストのキャッシュ動作を設定できます。
Request Memoization
Reactはfetch
APIを拡張して、同じURLとオプションを持つリクエストを自動的にメモ化します。これにより、React component tree内の複数の場所で同じデータのfetch関数を呼び出しても、一度だけ実行されます。
たとえば、あるルート全体で同じデータを使用する必要がある場合(例:Layout、Page、および複数のコンポーネント)、データをtreeの最上部でfetchしてコンポーネント間でpropsを転送する必要はありません。代わりに、データを必要とするコンポーネントでfetchし、ネットワークを介して同じデータの複数のリクエストを行うパフォーマンスの影響を心配することなくデータを取得できます。
- TypeScript
- JavaScript
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
Request Memoizationの仕組み
- ルートをレンダリング中、特定のリクエストが初めて呼び出されると、その結果はメモリ内に存在しないのでキャッシュ
MISS
となります; - したがって、関数は実行され、データは外部ソースから取得され、その結果はメモリに保存されます;
- 同じレンダリングパスでリクエストが再度呼び出された場合、キャッシュ
HIT
となり、データは関数を実行せずにメモリから返されます; - ルートのレンダリングが完了し、レンダリングパスが完了すると、メモリは「リセット」され、すべてのrequest memoizationエントリがクリアされます;
知っておくとよいこと:
- Request memoizationはReactの機能であり、Next.jsの機能ではありません。ここでは、他のキャッシュメカニズムとどのように相互作用するかを示すために含まれています;
- メモ化は、
fetch
リクエストのGET
メソッドのみに適用されます;- メモ化はReact Component treeのみに適用されます、つまり:
- それは
generateMetadata
、generateStaticParams
、Layouts、Pages、および他のServer Componentsにおけるfetch
リクエストに適用されます;- Route Handlersでの
fetch
リクエストには適用されません、なぜならそれらはReact component treeの一部ではないからです;fetch
が不適合な場合(例:いくつかのデータベースクライアント、CMSクライアント、またはGraphQLクライアント)、Reactのcache
関数を使用して関数をメモ化できます;