キャッシュしない指定
cache: 'no-store' を fetch に渡すと、そのリクエストはキャッシュされず毎回最新のデータを取得します。
// 毎リクエストで最新を取得
const data = await fetch('/api/dashboard', { cache: 'no-store' });
revalidatePath / revalidateTag との違い
cache: 'no-store' | revalidatePath / revalidateTag | |
|---|---|---|
| キャッシュ | そもそも作らない | キャッシュを作り、後から無効化する |
| データ取得 | 毎リクエストでフェッチ | キャッシュが有効な間はキャッシュを返す |
| 更新トリガー | 不要(常に最新) | Server Action などで明示的に呼ぶ |
| 向いている場面 | リアルタイム性が必要・ユーザー固有データ | 操作後に即時反映したい・定期更新で十分 |
no-store はキャッシュを「作らない」選択。revalidatePath / revalidateTag は「作ったキャッシュを後から無効化する」選択です。目的が根本的に異なります。
向いている場面
// ユーザーのセッション情報(人によって異なる)
const session = await fetch('/api/me', { cache: 'no-store' });
// リアルタイム在庫数(常に最新が必要)
const stock = await fetch('/api/products/123/stock', { cache: 'no-store' });
// 管理画面のデータ(キャッシュよりも正確さを優先)
const adminStats = await fetch('/api/admin/stats', { cache: 'no-store' });
ルート全体を動的にする
ページ内の fetch に no-store が含まれると、そのルートは動的レンダリング(リクエストごとにサーバーレンダリング)になります。
ルート単位でまとめて動的にしたい場合は export const dynamic = 'force-dynamic' を使います。
// app/dashboard/page.tsx
export const dynamic = 'force-dynamic'; // このルート全体を動的レンダリングにする
export default async function DashboardPage() {
const data = await fetch('/api/dashboard'); // cache オプション不要
// ...
}
乱用時の注意
no-store はシンプルですが、すべての fetch に使うとキャッシュの恩恵がなくなります。
// ❌ 変わらないコンテンツに no-store を使うとサーバー負荷が増える
const config = await fetch('/api/config', { cache: 'no-store' });
// ✅ 変わらないコンテンツは force-cache か next.revalidate を使う
const config = await fetch('/api/config', { cache: 'force-cache' });
const posts = await fetch('/api/posts', { next: { revalidate: 3600 } });
キャッシュを有効にする方法(force-cache / revalidate / tags)は → fetch cache
キャッシュ設計の全体像は → Next.js キャッシュ設計