半年くらい前の話ですが、2025年10月21日にNext.js 16が正式にリリースされましたね。
Cache Components という概念自体はNext.js 16 から導入されたもので、キャッシュが明示的に制御できるようになってます。
use cacheディレクティブを書いた場所だけがキャッシュされ<Sunpense>を使ってコンポーネント単位でのキャッシュも可能になりました。
まぁ記事の登板もあることですし、今回はNext.js16 の「Cache Components」についての使い方を中心に備忘録も兼ねてまとめます!
Next.js AppRouterの4つのキャッシュ
Next.js AppRouterでのキャッシュの種類は下記の4パターン。
- Request Memoization: 同じリクエストの重複排除のこと。異なるコンポーネントで同じfetchを呼んでも実行は1回のみ。Next.jsが自動的にやってくれる機能。
- Data Cache: fetchオプションでキャッシュの実装を操作するもの。
- Full Route Cache: 静的レンダリング(SSG、ISR)で機能するページ単位のキャッシュ。 RSCペイロードとhtmlでサーバー側にキャッシュする仕組み。
- Router Cache: クライアントのメモリ内に一時的に「RSCペイロードのみ」をキャッシュする仕組み。 Next.jsの<Link>コンポーネントを使用することで機能します。
Next.js16 の新機能"use cache"
新しい機能Cache Componentsについて、何ができるようになったか。
use cacheを使用してキャッシュ設定をシンプルに。use cacheを書いた場所だけがキャッシュされ、キャッシュが明示的に制御できるようになった。<Suspense>で囲むことでコンポーネントを分離でき、コンポーネント単位でのキャッシュ指定が可能になった。
従来のNext.js15まではfetchがデフォルトでキャッシュされており、どこがキャッシュされているのか、いないのかが分かりにくく予測しないキャッシュが起きやすかった状態でした。
デフォルトで勝手にキャッシュされるので、無効化するにはfetch(URL, { cache: 'no-store' }) の追加が必要でした。
一方でNext.js16はキャッシュが必要な場合にはuse cacheを指定するというやり方に変更し、明確にシンプルな方法になりました。
また従来はfetch経由でしかNext.jsのData Cacheを活用できませんでしたが、DBクエリなどfetchを使わない非同期関数にも直接キャッシュを適用できるようになりました。
実装方法
next.config.js ファイルで Cache Components を有効にする必要があります。
この設定により、Cache Components の機能が利用可能になります!
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
cacheComponents: true,
};
export default nextConfig;
キャッシュしたいコンポーネントの先頭に use cache ディレクティブを追加します。特定の関数だけキャッシュしたい 場合は関数の中に記述します。
'use cache'
async function getPosts() {
const res = await fetch('<https://api.example.com/posts>')
return res.json()
}
export default async function PostList() {
const posts = await getPosts()
return (
<ul>
{posts.map(post => <li>{post.title}</li>)}
</ul>
)
}
fetch関数に対してuse cacheをつけないとどうなるの?
Next.js16からはキャッシュをするにはuse cacheを追加する必要になりましたが、use cacheもcacheオプションも何もつけない場合どうなるの?
cacheComponents: true で設定した場合エラーになります。 意図的にキャッシュを無効化する場合はfetch(url, { cache: 'no-store' }) は使用せず、<Suspense>で囲むだけです!(cacheComponents: false(デフォルト)の場合は従来通り no-store が使えます)
関数レベルでのキャッシュ
従来はページ単位でのキャッシュ指定しかできませんでしたが、use cache、<Suspense>を利用することでコンポーネント・関数レベルのキャッシュ設定が可能になりました。
それがどのようなメリットになるかというと、ひとつのページ内で静的レンダリング・動的レンダリングが混合でき、高速な静的配信と動的コンテンツの共存が可能になり、初期読み込み速度とUXを劇的に向上させます。(PPRというレンダリング手法)
Suspense
ページの他の部分と切り離して、個別に処理できるようにするのが<Suspense>の役割です。
<Suspense>で囲むことでコンポーネントを分離できるので、コンポーネント単位でキャッシュをしたい場合は、囲まれている中のコンポーネント内で指定します。
レンダリングについて
キャッシュの設定によりレンダリング手法が決まります。
「このページ・データをどう見せたいか?」(更新の頻度など)
↓
レンダリング方法を決める(SSG / ISR / SSR / PPR / CSR)
↓
それに応じたキャッシュを設定
という考え方。
レンダリング手法にもいくつかパターンがありますが今回は割愛しまーす!
例えば、
「microCMSからデータを持ってきてブログ記事を表示させる動的ルーディングページ」の場合
↓
レンダリング方法はSSG か ISR が最適(記事の内容は頻繁に更新されないため)
↓
キャッシュありが最適→ use cacheを追加する
みたいな感じで実装できます。
ちなみにnext.config.js ファイルで Cache Components をtrueにしなければ、従来通りのfetch の cache オプションがそのまま使えます。
まとめ
キャッシュの設定を考えるときは「このデータ、ページはどう見せたいか?」そのページに合わせた最適なパフォーマンスを考えて実装するフローが重要。
その答えが決まれば、use cache を使うかどうかも自然に決まります。
キャッシュ周りやレンダリング手法、データフェッチなどを分けて理解してしまう方が多位と思いますが、全てが繋がった感覚ですね!
別々の概念ではなく、ひとつの流れとして考えることが大切です!!
マークアップを中心に、JavaScriptやReact、Next.jsを使ってフロントエンドの開発をやっています。自分が関わったサイトが無事に公開されると嬉しいです!趣味はギターを弾くこと。猫と焼き芋が好き🐱🍠
ひらっち
フロントエンドエンジニア / 2022年入社