Next.js の 4 種類のキャッシュについて、公式ドキュメントを読んで疑問を解消した
Next.js の 4 種類のキャッシュについて、下記公式ドキュメントを参照しながら、疑問を解消していきます。
Request Memoization
Request Memoization 機能要約(公式ドキュメント参照)
Request Memoization は React の機能であり、Next.js の機能ではありません。
他のキャッシュ機構とどのように相互作用するかを示すために、Next.js のドキュメントのみ含まれています。
メモ化は、フェッチリクエストの GET メソッドにのみ適用されます。
メモ化は、React コンポーネントツリーのレンダリングが終了するまで、サーバーリクエストの有効期間を持続します。
疑問点 🤔 : 同じリクエストを投げることが無い気がするが、どのような場面で有効か
Next.js の Request Memoization は、同じリクエストが複数回送信された場合に、最初のリクエスト結果をメモ化し、以降の同じリクエストにはメモ化を返す仕組みです。これが有効となる場面について、いくつかの例を挙げます。
1. 複数のコンポーネントが同じデータを必要とする場合
アプリケーションの複数のコンポーネントが同じデータを必要とする場合、各コンポーネントが個別にリクエストを送信すると無駄が生じます。Request Memoization を使うことで、最初のリクエスト結果を共有し、重複したリクエストを避けることができます。
- 例
ユーザープロファイル情報を表示するヘッダーとサイドバーのコンポーネントがある場合、各コンポーネントが個別にリクエストを送信する代わりに、最初のリクエスト結果をメモ化し共有します。
2. ユーザーの素早い操作
ユーザーが素早く連続して同じ操作を行った場合(例えば、ページ遷移やフォーム送信など)、同じリクエストが短時間に複数回送信されることがあります。Request Memoization はこれらの重複リクエストを減らし、ネットワーク負荷を軽減します。
- 例
ユーザーがフィルタリング操作を行った際、同じフィルター条件で連続してリクエストが送信される場合、最初の結果をメモ化して返すことで、同じデータを再取得する必要がなくなります。
これらの場面では、Request Memoization が有効であり、パフォーマンスの向上とリソースの節約に役立ちます。
Data Cache
Data Cache 機能要約(公式ドキュメント参照)
Next.js には組み込みのデータキャッシュがあり、受信するサーバーリクエストやデプロイメントにまたがってデータフェッチの結果を永続化します。これは、Next.js がネイティブのフェッチ API を拡張して、サーバー上の各リクエストが独自の永続キャッシュセマンティクスを設定できるようにしたためです。
疑問点 🤔 : Data Cache と Request Memoization の違い(公式に記載があったので、そのまま書きます)
どちらのキャッシュ・メカニズムも、キャッシュされたデータを再利用することでパフォーマンスを向上させるのに役立ちますが、Data Cache は、リクエストの受信とデプロイメントにわたって永続的であるのに対し、Request Memoization はリクエストの有効期間しか持続しません。
Request Memoization では、レンダリングサーバーからデータキャッシュサーバー(CDN やエッジネットワークなど)やデータソース(データベースや CMS など)までのネットワーク境界を越えなければならない、同じレンダーパスの重複リクエストの数を減らすことができます。Data Cache を使用することで、オリジンのデータソースへのリクエスト数を減らすことができます。
Full Route Cache
Full Route Cache の機能要約(公式ドキュメント参照)
Next.js はビルド時にルートを自動的にレンダリングしてキャッシュします。これは、リクエストごとにサーバーでレンダリングする代わりに、キャッシュされたルートを提供できるようにする最適化で、ページロードの高速化をもたらします。
Full Route Cache がどのように機能するのかを理解するには、React がどのようにレンダリングを処理し、Next.js がどのように結果をキャッシュするのかを見るのが役に立ちます。
ビルド時にルートがキャッシュされるかどうかは、静的にレンダリングされるか動的にレンダリングされるかに依存します。静的ルートはデフォルトでキャッシュされますが、動的ルートはリクエスト時にレンダリングされ、キャッシュされません。
疑問点 🤔 : Full Route Cache は、Client Components を使っている場合でも機能するのか
機能はするが、Client Components か ServerComponents は関係ない。
Full Route Cache は、静的な API に対する Cache を提供する。
AppRouter の推奨としては、API を叩くのは ServerComponents に寄せることになるはずな為、結果的には ServerComponents の 静的な Route(API) のリクエストに対して Cache が有効になる。
- 例
app/blog/[slug]/page.js
など動的な Route(API) に対しては Full Route Cache は機能しない。
Cookie やヘッダー、Pages の searchParams プロップなどの動的な関数は、実行時に入力されるリクエスト情報に依存します。これらを使用すると、フルルートキャッシュからルートが除外され、言い換えると、ルートは動的にレンダリングされます。
Router Cache
Router Cache の機能要約(公式ドキュメント参照)
ユーザーがルート間を移動すると、訪問した Route Segment をキャッシュし、(ビューポート内の<Link>コンポーネントに基づいて)ユーザーが移動しそうなルートをプリフェッチします。
その結果、ユーザーのナビゲーション体験が向上します。
訪問したルートがキャッシュされるため、すぐに戻る/進むナビゲーションができ、プリフェッチと部分レンダリングにより、新しいルートへのナビゲーションが高速になります
ナビゲーションの間に全ページをリロードする必要がなく、React の状態とブラウザの状態が保持されます。
疑問点 🤔: Router Cache と Full Route Cache の違い(公式に記載があったので、そのまま書きます)
Router Cache は、ユーザーセッションの間、React Server Component Payload をブラウザに一時的に保存するのに対し、Full Route Cache は、複数のユーザーリクエストにわたって React Server Component Payload と HTML をサーバーに永続的に保存します。
Full Route Cache が静的にレンダリングされたルートのみをキャッシュするのに対し、Router Cache は静的にレンダリングされたルートと動的にレンダリングされたルートの両方に適用されます。
まとめ
詳細については公式ドキュメントを読むことをおすすめしますが、Next.js の Cache についての以前よりも理解深まったが方がいれば嬉しいです。
まだ理解が浅い部分もあるので、引続き Next.js のドキュメントを読んでいこうと思います、、
ここまで読んでいただきありがとうございました 🙌
Discussion