こんにちは!つつです!
この前next.jsのCache Componentsの挙動に振り回されたので、まとめます。
Web アプリの世界で「キャッシュ」とは、
一度計算したり取得した結果を保存しておき、次回以降はそれを使い回す仕組み のことです。
Cache Components は Next.js 15 以降で導入された新しいキャッシュモデルで、Next.js 16 世代では cacheComponents フラグで本格的に利用できます。
App Router(app/)で、
みたいな「静的・キャッシュ・動的を1ルート内で混在」させやすくするための機能です。
Next.jsの公式ドキュメント
中心になるのがこのあたり
use cacheuse cache: remoteuse cache: private💡補足:Cache Components は RSC(サーバーコンポーネント)専用
Cache Components が利用できるのは Server Component またはサーバー側の関数だけで、
"use client" を含む Client Component は対象外です。
キャッシュしたい処理は Server Component 側に寄せる必要があります。
普通のコンポーネントは、呼ばれるたびに表示に必要な処理を毎回行いレスポンスを返す。
キャッシュコンポーネントは2回目以降に同じリクエストがきたらキャッシュされたレスポンスを返します。

まず next.config.{js,ts} でフラグをオン にします:
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
}
export default nextConfig
これで Cache Components 機能が有効になります。
// app/page.tsx
'use cache'
export default async function Page() {
const data = await getData()
return <main>{data.title}</main>
}
"use cache" を書くと// コンポーネントレベル
export async function Card({ id }: { id: string }) {
'use cache'
const data = await getPost(id)
return <div>{data.title}</div>
}
// 関数レベル
export async function getPost(id: string) {
'use cache'
const res = await fetch(`https://example.com/posts/${id}`)
return res.json()
}
キャッシュ対象の範囲は、use cache を書く場所で決まります。
書く場所 | キャッシュ対象 |
|---|---|
ファイル先頭 | そのファイル内のすべてのエクスポート |
コンポーネント内 | そのコンポーネントの戻り値 |
関数内 | その関数の戻り値 |
これが分かると、「キャッシュが効くと思ったのに効かない」問題は解決しやすいと思います。
Next.js には少なくとも 2種類のキャッシュ があります:
種類 | 何をキャッシュするか | 代表的な指定方法 |
|---|---|---|
fetch のキャッシュ | HTTP レスポンス |
|
Cache Components | コンポーネント / 関数の戻り値 |
|
ポイントは、この2つは完全に別レイヤー だということです。
'use cache'
export async function getData() {
// 毎回リクエストは飛ぶ
const res = await fetch('https://example.com/posts', {
cache: 'no-store',
})
// でも getData の「戻り値」は Cache Components によってキャッシュされる
return res.json()
}
fetch は毎回 API を叩くgetData() の戻り値はキャッシュ済みのものが再利用されるつまり:
use cache の設定と考えると整理しやすいです。
Next.js には 3 種類のキャッシュ指示子があります:
use cache(基本形)use cache: remote(共有キャッシュ:外部ストア)use cache: private(ユーザーごと)それぞれの違いは、ざっくり次の 3 点です:
もっともシンプルなキャッシュ方式。
静的コンテキスト向け。
use cache を書いた関数やコンポーネントの 中では cookies() や headers() は使えません。use cache 側に渡すことは可能です。cacheHandlers でリモートキャッシュに変えることもできます)。export async function getPublicPosts() {
'use cache'
const res = await fetch('https://example.com/posts')
return res.json()
}
キャッシュ結果はサーバー側のキャッシュハンドラに保存され、全ユーザーで共有されます(KV / Redis などのリモートキャッシュに置くイメージ)。
use cache: サーバー内のローカルキャッシュuse cache: remote: 外部キャッシュ(Redis / KV)に保存して全体で共有export async function getExchangeRate(base: string, target: string) {
'use cache: remote'
const res = await fetch(
`https://api.example.com/rate?base=${base}&target=${target}`
)
return res.json()
}
ログインユーザーごとにキャッシュを分離したい場合の専用モード。
import { cookies } from 'next/headers'
export async function getMyDashboardData() {
'use cache: private'
const session = cookies().get('session_id')?.value
const res = await fetch('https://example.com/api/me', {
headers: { 'x-session-id': session ?? '' },
})
return res.json()
}
種類 | 共有範囲 | ユーザー依存情報 | 向いている用途 |
|---|---|---|---|
use cache | サーバー内 / ビルド単位 | ❌ 使わない前提 | 公開記事一覧・定数的データ |
use cache: remote | 全サーバー・全リージョン | ❌ 使用不可 | 為替・ランキングのような共通データ |
use cache: private | ユーザーごと | ✅ 使用可能 | マイページ・個別設定・カート |
'use cache' だけ使った場合は、Next.js が 自動で定期的に再検証します。
より細かく制御したい場合は cacheLife()。
use cache だけを指定した場合は、Next.js が default プロファイル(stale 5分 / revalidate 15分 / expire 1年)に基づいて自動再検証します。
ただし挙動を明示したい場合は、cacheLife('hours') などでプロファイルを指定するのがおすすめです。
import { cacheLife } from 'next/cache'
export async function getPosts() {
'use cache'
cacheLife('hours') // 数時間おきに更新
return fetch('https://example.com/posts').then(r => r.json())
}
プリセット | 意味 | 使うケース |
|---|---|---|
| 数秒 | 株価、スポーツスコア |
| 数分 | タイムライン |
| 数時間 | API 全般 |
| 1日1回 | ブログ一覧 |
| 不変に近い | アーカイブ |
Next.js 16 の Cache Components は、従来よりも 細かな単位でキャッシュ戦略をコントロールできる新しい仕組み です。
ページ全体だけでなく、コンポーネントや関数レベルでキャッシュを明示できるため、
「静的」「キャッシュ」「動的」を 1 つのルートで柔軟に混在させることが可能になります!