言語を切り替える
テーマを切り替える

Next.js SSR vs SSG vs ISR:レンダリング戦略選択ガイド

「なぜトップページの読み込みに3秒もかかるんだ?」上司が画面を睨みつけ、私は Chrome DevTools のウォーターフォールチャート——TTFB(Time To First Byte)の赤いバーが蛇のように伸びている——を凝視していました。その時初めて、最初のレンダリング戦略選びで失敗していたことに気づきました。

これは珍しいケースではありません。Next.js の GitHub Issues やコミュニティでは、毎日誰かが尋ねています。「SSR と SSG どっちがいい?」「ISR 設定したのに効かないんだけど?」正直、私も最初はドキュメントを読んでも、実際のプロジェクトでどれを選ぶべきか自信がありませんでした。

あなたも似たような悩みを持っていませんか?

  • SSR を選んだら、TTFB が遅すぎてユーザーが離脱する
  • SSG を選んだら、ちょっとした修正でサイト全体の再ビルドが必要になった
  • ISR は理想的に見えるけど、設定してもキャッシュが更新されない

実は、これらの戦略に「最強」はありません。「最適」があるだけです。今日は、どのシナリオでどの戦略を使うべきか、そしてよくある落とし穴を回避する方法を徹底解説します。

40-60%
SSGの高速化率 (対SSR)
AWS データ
50ms
SSG TTFB
Vercel 公式データ
200-500ms
SSR TTFB
Vercel 公式データ
2.3s→0.8s
ISR 導入効果
某ECサイト実測値
数据来源: AWS、Vercel 公式データおよび実戦事例

まず理解しよう:3つのレンダリング戦略の違い

選び方の前に、概念を「お弁当屋さん」に例えて直感的に理解しましょう。

SSG(Static Site Generation):作り置き弁当

あなたは弁当屋を開きました。毎日朝一番に100個の弁当を作ってカウンターに並べます。客が来たら、すでにできている弁当を渡すだけ。これが SSG です。

具体的には:

  • いつ生成するかnext build 実行時。全ページの HTML を事前に作ります。
  • ユーザー訪問時:CDN が事前生成された HTML を即座に返します。超高速です。
  • 向いている場面:内容が変わらないページ。企業サイト、製品紹介、ブログ記事など。

メリット

  • 爆速。SSR より圧倒的に速い。TTFB はほぼゼロ。
  • サーバー負荷ほぼゼロ。CDN が全部やってくれます。
  • 安い。静的ホスティングはコストが低い。

デメリット

  • 更新が大変。一箇所直すだけでサイト全体の再ビルドが必要。
  • ビルド時間が長い。数千ページあると数十分かかることも。
  • パーソナライズ不可。全員に同じ内容しか見せられない。

「事前準備」で速度を買う戦略です。

SSR(Server-Side Rendering):オーダーメイド弁当

今度は作り置きをやめました。客が来て注文してから、その場で調理して渡します。これが SSR です。

具体的には:

  • いつ生成するか:ユーザーがリクエストするたびに、サーバーで HTML をリアルタイム生成。
  • ユーザー訪問時:サーバーが DB を叩き、API を呼び、レンダリングして返すのを待ちます。
  • 向いている場面:リアルタイム性やパーソナライズが必要なページ。

メリット

  • 常に最新。1秒前のデータ変更も反映される。
  • パーソナライズ可能。ユーザーの権限や Cookie に応じて違う内容を出せる。
  • リクエスト情報(ヘッダー、クエリパラメータ)にアクセスできる。

デメリット

  • 遅い。サーバー処理が終わるまでユーザーは待たされる。
  • サーバー負荷が高い。アクセス集中でダウンするリスクがある。
  • コストが高い。サーバーを常時稼働させる必要がある。

某 EC サイトの事例では、SSR を採用した結果、トップページの表示に 2.3秒 もかかっていました。

ISR(Incremental Static Regeneration):作り置き + 定期補充

今回は賢くなりました。朝に弁当を作っておきますが、1時間ごとに新しい弁当を作って入れ替えます。客は基本的に作り置きを受け取りますが、中身はそこそこ新しいです。これが ISR です。

具体的には:

  • 初回ビルドnext build で静的 HTML を生成(SSGと同じ)。
  • その後の更新:設定した revalidate 時間(例:60秒)が過ぎると、バックグラウンドでページを再生成してキャッシュを更新。
  • ユーザー訪問時:ほぼ常にキャッシュされた HTML が返る(高速)。

バランスの妙

  • SSG の速度(静的ファイルを返す)
  • SSR の鮮度(定期的に更新される)
  • サイト全体再ビルド不要

設定は簡単(App Router):

// app/posts/[id]/page.tsx
export const revalidate = 60; // 60秒後に再検証

export default async function Post({ params }) {
  const post = await getPost(params.id);
  return <div>{post.content}</div>;
}

落とし穴

  • ローカル開発環境(next dev)では効かない(常に SSR 扱いになる)。
  • ホスティング環境依存。Vercel は完璧だが、他プラットフォームでは設定が必要な場合も。

正直、今の私はほとんどこれ(ISR)を使っています。SSG と SSR のいいとこ取りで、本当に快適です。

デシジョンツリー:どの場面で何を使う?

では、あなたのプロジェクトではどれを選ぶべきか? 以下のフローチャートで判断してください。

ステップ1:3つの質問に答える

Q1:内容はパーソナライズ(ユーザーごとに違う)が必要?

YES なら問答無用で SSR(またはクライアントサイドフェッチ)。

  • ダッシュボード、マイページ、カート画面など。
  • 事前生成できないからです。

Q2:内容はどれくらいの頻度で更新される?

  • 秒単位〜分単位SSR
    • 株価、スポーツ実況、チャット。リアルタイム性が命。
  • 分単位〜時間単位ISR
    • ニュースサイト、ブログトップ、商品一覧、在庫状況。
    • revalidate: 300(5分)などで十分対応可能。
  • ほとんど更新しないSSG
    • 企業情報、ヘルプセンター、規約。

Q3:トラフィック(アクセス数)は?

  • 超高トラフィックSSGISR
    • CDN で捌けるようにしないと、サーバー代で死にます。SSR は避けるべき。
  • 中〜低トラフィック:どれでもOK。
    • リアルタイム性が重要なら SSR でも耐えられます。

ステップ2:シーン別早見表

SSG 推奨

  • ✅ 企業コーポレートサイト
  • ✅ LP(ランディングページ)
  • ✅ ブログ記事詳細(公開後あまり修正しない)
  • ✅ ドキュメント、マニュアル

SSR 推奨

  • ✅ SNS のフィード(Twitterライクなもの)
  • ✅ ユーザー設定画面
  • ✅ 注文履歴、決済画面
  • ✅ 複雑な検索結果ページ

ISR 推奨(私のイチオシ)

  • ✅ ブログトップ、記事一覧
  • ✅ ニュースサイト
  • ✅ EC の商品詳細(価格や在庫が変動する)
  • ✅ 口コミ・レビューページ
  • ✅ 天気予報

ステップ3:ハイブリッドが正解

「サイト全体で1つの戦略」にする必要はありません。Next.js の真骨頂は、ページごとに戦略を変えられることです。

私たちの EC プロジェクトの実例:

  • トップページ:ISR(10分更新)。キャンペーンバナーなどが変わるため。
  • 商品一覧:ISR(5分更新)。
  • 商品詳細:ISR(1分更新)。在庫切れを反映するため短めに。
  • カート・決済:SSR。絶対に最新で正確でないといけない。
  • マイページ:SSR。ユーザー情報。
  • 会社概要・規約:SSG。ほぼ不変。

これで、パフォーマンス(速度)とリアルタイム性のバランスが取れます。

一言で言うと?

迷ったら ISR。

静的なら SSG、リアルタイムなら SSR ですが、ISR はその中間で最も失敗が少ない安全策です。

3大トラブルと解決策

理論は分かっても、現場ではハマります。私が踏んだ地雷を共有します。

トラブル1:ISR の revalidate が効かない

症状revalidate: 60 と書いたのに、何分待っても内容が更新されない。

原因と対策

  1. 開発モード (next dev) だった

    • ISR は next build && next start(本番モード)でしか動きません。開発中は常にリクエスト毎に再生成されます(デバッグしやすさのため)。
    • 対策:必ずビルドして検証する。
  2. CDN キャッシュの設定漏れ

    • Cloudflare などを前段に置いている場合、CDN が古い HTML を長くキャッシュしてしまい、Next.js サーバーまでリクエストが届いていない可能性があります。
    • 対策:CDN 側で Cache-Control ヘッダーを尊重する設定にするか、パスごとのキャッシュルールを見直す。

トラブル2:SSR の首屏ロードが遅すぎる

症状:SSR にしたら画面が白くなる時間が2〜3秒続く。

原因:サーバー側でのデータ取得(API呼び出しなど)が遅い。直列で await している。

対策

  1. Streaming SSR と Suspense を使う

    • 全部待たずに、殻(シェル)だけ先に返す。
    export default function Page() {
      return (
        <div>
          <Nav />
          <Suspense fallback={<Skeleton />}>
            <SlowDataComponent />
          </Suspense>
        </div>
      )
    }

    これならユーザーは即座に何かを見ることができます。

  2. 並列リクエスト

    • await を連打せず、Promise.all で同時にデータを取る。

トラブル3:SSG のビルドが終わらない

症状:ページ数が5000を超えたあたりから、ビルド時間が30分を超え、タイムアウトでコケるように。

対策

  1. generateStaticParams (getStaticPaths) を絞る

    • 全ページをビルド時に作ろうとしない。過去の記事やアクセスの少ない商品はビルド時には生成せず、初回アクセス時に生成(fallback)させる。
    export async function generateStaticParams() {
      // 最新の100件だけ事前生成
      const posts = await getLatestPosts(100);
      return posts.map(p => ({ slug: p.slug }));
    }
    // 他のページはアクセス時に生成(SSR的に振る舞い、その後キャッシュされる)
    export const dynamicParams = true;
  2. 増分ビルド (Incremental Builds)

    • Vercel などのプラットフォームなら、変更があったページだけを再ビルドしてくれます。

結論

SSR、SSG、ISR の選択に「正解」はありませんが、「定石」はあります。

  1. 基本は SSG/ISR で速度を確保する。
  2. パーソナライズが必要な部分だけ SSR(またはクライアントフェッチ)にする。
  3. 迷ったら ISR で様子を見る。

前述の「トップページが3秒かかる」案件は、結局 SSR から ISR (revalidate: 60) に変更し、0.8秒まで短縮しました。上司もニッコリです。

あなたのプロジェクトでも、まずは ISR を検討してみてください。もし実装で詰まったら、Twitter で聞いてください。

FAQ

SSR、SSG、ISR の最大の違いは何ですか?
HTML が生成されるタイミングです。SSG は「ビルド時」、SSR は「リクエスト時(毎回)」、ISR は「ビルド時 + 定期的なバックグラウンド更新」です。
ECサイトの商品ページはどれがいいですか?
ISR が推奨されます。価格や在庫が変わる可能性があるため完全な SSG は不向きですが、SSR だと遅すぎます。ISR なら高速表示しつつ、在庫切れなどを数分以内に反映できます(購入ボタンを押した時の最終チェックは API で行うのが定石です)。
ISR は Vercel 以外でも使えますか?
はい、使えますが、構成が複雑になる場合があります(共有ストレージやキャッシュの仕組みが必要)。Netlify など主要なホスティングはサポートしていますが、完全自前サーバー(Docker + Node.js)の場合は、Next.js 自体が ISR のサーバーとして機能するので動作はしますが、キャッシュ共有の設定(Redisなど)が必要になることがあります。
Next.js 15 の React Server Components はこれらとどう関係しますか?
Server Components はアーキテクチャの話で、SSR/SSG/ISR はレンダリング戦略の話です。Server Components はデフォルトでサーバーでレンダリングされるため、SSG/ISR と非常に相性が良く、ビルド時に実行して結果を静的ファイルに焼き付けることができます。

5 min read · 公開日: 2025年12月19日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事