📖

Next.js14のSSG / SSR / ISR の書き方(フェッチ単位)

に公開1

fetch のオプションnext/cache のAPIで、ページ全体の dynamic/revalidate を書かなくても “その取得だけ” を SSG/SSR/ISR 相当にできます。

フェッチ単位の指定(App Router)

SSG 相当(静的キャッシュ)

// デフォルトがこれ(= Data Cache に保存)
await fetch('https://api.example.com/items', { cache: 'force-cache' });
  • そのルートが動的要素(headers(), cookies() など)を使っていなければ静的にキャッシュされます。 (Next.js)

SSR 相当(毎リクエスト)

// どちらか一方でOK(両方はNG)
await fetch('https://api.example.com/items', { cache: 'no-store' });
// または
await fetch('https://api.example.com/items', { next: { revalidate: 0 } });
  • 「その fetch だけ」キャッシュを使わず 毎回取得。 (Next.js)

代替:noStore() を使うと、その処理スコープ全体を動的扱いにできます。

import { unstable_noStore as noStore } from 'next/cache';
noStore();
// …DBクエリや fetch など

(Next.js)

ISR 相当(時間で再検証)

// 60秒ごとにバックグラウンド再生成
await fetch('https://api.example.com/items', { next: { revalidate: 60 } });
  • フェッチごとに有効期限を設定できます(ルート全体ではなく“この取得だけ”に適用)。 (Next.js)

タグでオンデマンド再検証(任意のタイミングで)

// 取得時にタグ付け
await fetch('https://api.example.com/items', { next: { tags: ['items'] } });

// サーバーアクション or Route Handler から無効化
import { revalidateTag } from 'next/cache';
revalidateTag('items');
  • 該当タグのキャッシュを無効化→次アクセス時に再取得。 (Next.js)

注意点(重要)

  • cache: 'no-store'next: { revalidate: N }同時指定は不可(衝突は無視され警告)。 (Next.js)
  • headers()cookies() を使うと、そのルートは動的レンダリング扱いになります。 (Next.js)
  • 同じルート内で複数 fetch に異なる revalidate を指定した場合、最小の値が採用されることがあります。 (Next.js)

どこに書く?

  • これらは Server Componentpage.tsx / layout.tsx 内のサーバーコード)や Route Handler で記述します。
  • Client Component では使えないため、必要なら「クライアント → Route Handler/Server Action を呼ぶ」構成にしてください。 (Next.js)

まとめ(短縮)

  • SSR(毎回): fetch(..., { cache: 'no-store' })next: { revalidate: 0 }、あるいは noStore(). (Next.js)
  • ISR(定期): fetch(..., { next: { revalidate: 60 } }). (Next.js)
  • SSG(静的): fetch(..., { cache: 'force-cache' })(実質デフォルト)。動的APIを使わない。 (Next.js)

Discussion

Honey32Honey32

公式ドキュメントの noStore の説明には

In version 15, we recommend using connection instead of unstable_noStore.

https://nextjs.org/docs/app/api-reference/functions/unstable_noStore?utm_source=chatgpt.com

とあります。この記事をふくめ、maro さまが投稿しているもう一件の記事についても Next.js 14 を前提にしているのにもかかわらず、それが明示されていないと見受けられます。

最新情報を確認すること、もしくは Next.js 14 を前提にしている旨を明記することをお勧めします。