🧩

今更SSG / ISR / SSR / CSR の違いをまとめてみた

に公開

Next.js を使っていると必ず出てくる

  • SSG
  • ISR
  • SSR
  • CSR

の 4 つ。

「なんとなく理解したつもり…でも、
結局どう違うの?コード的にどう書くの?
ここが一番つまずきやすいポイントです。

この記事では、
“本質レベルで理解できる説明” + “実際のコードでの書き分け”
を 1 つにまとめて、完全に腹落ちする形に整理します。


🎯 結論(これが分かれば全部理解できる)

Next.js の 4 方式の違いは、

👉 **React が動く前の“初期 HTML”を

どこで・いつ作るかの違いだけ。**

最終的にはどの方式でも React が動いて UI は動的になります。
違うのは 最初に返す HTML をどこで生成するか


🍱 弁当の例えで 4 方式を完全理解する

方式 HTML を作る場所 いつ作る?
SSG 店(サーバ/ビルド) デプロイ前にまとめて作る
ISR 作り置きしつつ、一定時間で作り直す
SSR 注文が来てから毎回作る
CSR 家(ブラウザ) 食材だけ渡して、家で調理

React(調理道具)はどれでも最終的に動きます。
違うのは “どこでそれを使って初期 HTML を作るか” だけ。


🧩 各方式のポイント

■ SSG(Static Site Generation)

  • デプロイ時に HTML を生成
  • 初回表示が爆速
  • 内容はしばらく固定
  • SEO に強い
    → トップページ、ブログ、ヘルプページ に最適

■ ISR(Incremental Static Regeneration)

  • SSG だけど “◯ 秒ごとに作り直す”
  • 「速さ + 新鮮さ」の両立
    → ニュース一覧、商品一覧 に最適

■ SSR(Server Side Rendering)

  • リクエストごとに HTML(初期 HTML)を生成
  • 常に最新データ
  • ユーザーごとに内容が違うページに強い
    → ダッシュボード・マイページに最適

■ CSR(Client Side Rendering)

  • 初期 HTML は最低限
  • 画面の構築は全部ブラウザ側で
  • SEO は弱い
    → 設定画面、管理画面、フォーム多めの UI に向いてる

🎨 4 方式の比較表

方式 HTML 生成のタイミング 初回速度 データ更新 SEO
SSG ビルド時 🌟 最速 ❌ 固定 🌟 強い
ISR ビルド時+再生成 🌟 速い ◯ 更新される 🌟 強い
SSR リクエスト時 △ 普通 🌟 最新 🌟 強い
CSR クライアント ❌ 遅め 🌟 最新 △ 弱い

🔥 では、App Router ではどう書くべき?

ここからは App Router(app/ ディレクトリ)前提でのコード例 をまとめます。

Next.js 13+ の App Router では、

  • 何も指定しないと 静的寄り(SSG 的)
  • revalidate で ISR
  • dynamic = "force-dynamic" で SSR
  • 'use client' で CSR

と書き分けます。


① SSG(デフォルト)

app/posts/page.tsx
async function getPosts() {
  const res = await fetch("https://example.com/api/posts");
  return res.json();
}

export default async function PostsPage() {
  const posts = await getPosts();

  return (
    <main>
      <h1>Posts (SSG)</h1>
      {posts.map((p: any) => (
        <div key={p.id}>{p.title}</div>
      ))}
    </main>
  );
}
  • fetch のデフォルト = "force-cache"
  • 特に設定なし
    → SSG 的な(静的に生成される)ページ

② ISR(◯ 秒ごとに再生成)

app/news/page.tsx
export const revalidate = 60; // 60秒ごとに再生成

async function getNews() {
  const res = await fetch("https://example.com/api/news");
  return res.json();
}

export default async function NewsPage() {
  const news = await getNews();

  return (
    <main>
      <h1>News (ISR)</h1>
      {news.map((n: any) => (
        <div key={n.id}>{n.title}</div>
      ))}
    </main>
  );
}

③ SSR(毎回サーバで HTML を生成)

方法 A:ページ全体を「動的」にする

app/dashboard/page.tsx
export const dynamic = "force-dynamic";

async function getUser() {
  const res = await fetch("https://example.com/api/me", {
    cache: "no-store",
  });
  return res.json();
}

export default async function DashboardPage() {
  const user = await getUser();

  return (
    <main>
      <h1>Dashboard (SSR)</h1>
      ようこそ {user.name} さん
    </main>
  );
}

方法 B:API Route を SSR 的にする

app/api/data/route.ts
export const dynamic = "force-dynamic";

export async function GET() {
  const data = await fetch("https://example.com/api/live", {
    cache: "no-store",
  }).then(r => r.json());

  return Response.json(data);
}

④ CSR(Client Side Rendering)

app/tools/page.tsx
"use client"; // CSR にする

import { useEffect, useState } from "react";

export default function ToolsPage() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch("/api/client-data")
      .then(res => res.json())
      .then(setData);
  }, []);

  if (!data) return <p>Loading...</p>;

  return (
    <main>
      <h1>Tools (CSR)</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </main>
  );
}

🧩 書き分けチートシート

// SSG(デフォルト)
// → Server Component + デフォルトfetch

// ISR
export const revalidate = 60;

// SSR
export const dynamic = "force-dynamic";
// or fetch(..., { cache: "no-store" })

// CSR
("use client"); // + useEffect/useState など

🎯 まとめ

Next.js の SSG / ISR / SSR / CSR の違いは、

React が動く前の “初期 HTML” を
どこで・いつ生成するかの違いだけ。

そして App Router では、

  • 何も指定しない:SSG 的
  • revalidate:ISR
  • dynamic="force-dynamic":SSR
  • 'use client':CSR

とコードでハッキリ書き分けられます。

「このページは本当に SSR が必要?」
「ヘルプページは SSG + ISR で十分?」
「ログイン後 UI は CSR のほうが軽い?」

など、設計判断がとてもクリアになるはずです。


質問や「このページはどれを採用すべき?」などあれば、
気軽にコメントください 🙌🔥

GitHubで編集を提案

Discussion