SSR・CSR・SSG・ISR・ISGは、ページのHTMLを「どこで」「いつ」作るかで分けた呼び名です。サーバーかブラウザか、リクエストのたびかビルド時か、公開後に作り直すかどうかの組み合わせで5つに分かれます。この記事では5方式を1枚の表で比べたうえで、SSG・ISG・ISRの違いをNext.js 16.4.3で実際に動かして確かめた結果と、Nuxt・Astro・Gatsbyでの呼び名、ページごとの選び方をまとめます。
まとめ
- SSR(Server-Side Rendering)はリクエストのたびにサーバーでHTMLを作る。CSR(Client-Side Rendering)はブラウザがJavaScriptを実行して画面を描く。
- SSG(Static Site Generation)はビルド時にHTMLを作り、そのまま配信する。データを更新しても再ビルドするまで反映されない。
- ISR(Incremental Static Regeneration)は公開後に静的ページを作り直す。期限が切れた後のアクセスには、作り直しが終わるまで古いページを返し、裏で作り直す。
- ISG(Incremental Static Generation)はビルド時に作らなかったページを初回アクセス時に作って保存する挙動の通称。Next.jsの公式ドキュメントは「ISG」という略語を使っていない。
- 選び方はサイト単位ではなくページ単位。公開後に変わらないページはSSG、件数が多いページはISG、定期的に変わるページはISR、ログイン後の画面はSSRかCSRが基本。
5方式の違いを一覧で比較:HTMLを作る場所とタイミング
5方式を分けているのは「HTMLを作る場所」「作るタイミング」「公開後に作り直すか」の3点だけです。表示速度やSEOへの影響は、この3点から決まります。
| 方式 | HTMLを作る場所 | 作るタイミング | データ更新の反映 | 初期HTMLの本文 |
|---|---|---|---|---|
| SSR | サーバー | リクエストごと | 即時 | 入っている |
| CSR | ブラウザ | JavaScript実行後 | 即時 | 空(読み込み表示のみ) |
| SSG | ビルド環境 | ビルド時 | 再ビルドまで反映されない | 入っている |
| ISG | サーバー | 未生成ページの初回アクセス時 | 一度作ったら固定 | 入っている |
| ISR | サーバー | ビルド時+期限切れ後 | 期限切れ後の次のアクセス以降 | 入っている |
SSRとCSR:リクエスト時にサーバーかブラウザで描画
SSRはServer-Side Renderingの略で、アクセスのたびにサーバーがデータを取得してHTMLを組み立てます。ユーザーごとに中身が違うページ(マイページ、カート、管理画面の一覧)でも最新の状態をHTMLで返せる代わりに、アクセス数に比例してサーバーの処理が増えます。
CSRはClient-Side Renderingの略で、サーバーはほぼ空のHTMLとJavaScriptを返し、ブラウザ側でデータを取って画面を描きます。画面遷移が多い業務アプリやダッシュボードに向きますが、最初の表示はJavaScriptの読み込みと実行を待つ分だけ遅れます。2方式だけを詳しく比べたい場合はCSRとSSRの違いと使い分け|レンダリング方式を比較して実装で選ぶにまとめています。
SSG:ビルド時の静的HTML生成
SSGはStatic Site Generationの略で、ビルドの時点で全ページのHTMLを書き出し、CDNやWebサーバーからファイルとして配信します。リクエスト時に処理が走らないので最も速く、サーバーも要りません。弱点は2つで、ページ数に比例してビルド時間が延びることと、記事や商品の更新が再ビルドまで反映されないことです。ISGとISRは、この2つの弱点をそれぞれ埋めるために生まれました。
なお「SSG」はHugo・Astro・Jekyllのような静的サイトジェネレーター(ツール)を指すこともあります。ツールの選び方はSSGとは?静的サイトジェネレーターの仕組みと企業サイト採用の判断基準で扱っています。
ISR:公開後の静的ページ再生成
ISRはIncremental Static Regenerationの略で、Next.js 9.4(2020年5月11日)でベータとして導入され、Next.js 9.5(2020年7月27日)で安定版になりました。ページに有効期限(revalidateの秒数)を付け、期限が切れた後の次のアクセスには古いページを返しつつ、裏で新しいページを作ります。Next.jsの公式ガイドも「期限後の次のリクエストはキャッシュ済みの古いページを返し、新しい版の生成をバックグラウンドで始める」と説明しています。
この「古い版を返してから裏で作り直す」動きはHTTPのstale-while-revalidateと同じ考え方で、実際にNext.jsはそのヘッダーを返します(次の章で実測)。ヘッダーの意味はstale-while-revalidateとは?Cache-Controlの設定例とReact SWR・CDN別の挙動を解説で詳しく説明しています。組み込み開発で「ISR」と言えば割り込み処理(Interrupt Service Routine)のことで、Webのレンダリングとは無関係です。
ISG:未生成ページの初回アクセス時生成(公式用語ではない)
ISGはIncremental Static Generationの略として日本語の技術記事でよく使われ、「ビルド時に一部のページだけ作り、残りは最初にアクセスされた時に作って保存する」挙動を指します。Next.jsでいえばPages RouterのgetStaticPathsでfallback: trueか'blocking'を返したとき、App RouterではgenerateStaticParamsに載せなかったパスをdynamicParams(既定でtrue)で受けたときの動きです。
この呼び名の出どころはNext.js自身です。Next.js 9.4の発表記事(2020年5月11日)は、9.3で入ったfallback: trueを例に「ビルド後に新しいページを追加できる」仕組みをIncremental Static Generationと呼び、同じ記事で既存ページを作り直す仕組みとしてISRを紹介し、両者を「incremental features(ページの追加と遅延更新)」とまとめて呼んでいます。ところが現行のNext.js 16.4.3のドキュメント一式(GitHubのv16.4.3タグ)を検索すると、「ISG」という略語は0件、「Incremental Static Generation」も古い記述に2箇所(getStaticPropsの解説とassetPrefixの注記)残るだけで、リンクが付いているassetPrefix側のリンク先もISRのガイドです。今の公式の説明はgenerateStaticParamsとdynamicParamsの挙動としてであり、ISGを独立した方式としては扱っていません。社内や発注先と話すときは「未生成ページの初回生成(fallback/dynamicParams)」と具体的に言ったほうが誤解がありません。
ISGとISRの違いは「一度作ったページを作り直すかどうか」です。getStaticPathsのリファレンスは、fallback: trueや'blocking'は生成済みのページを更新しないと明記し、更新したいときはfallback: 'blocking'とISRを組み合わせるよう案内しています。
SSG・ISG・ISRの違いをNext.js 16.4.3で実測
違いを言葉ではなく挙動で確かめるため、Next.js 16.4.3・React 19.3.1・Node.js 26.5.0で5方式のページを1つずつ作り、next buildとnext startで動かしました(2026年10月25日)。各ページは生成時刻を表示するだけの最小構成です。
ビルド出力の記号(○・●・ƒ)による方式の見分け方
next buildの最後に出るルート一覧が、各ページの方式を示します。
Route (app) Revalidate Expire
┌ ○ /_not-found
├ ƒ /api/revalidate
├ ○ /csr
├ ○ /isr 10s 1y
├ /posts/[id]
│ ├ ● /posts/1
│ └ ● /posts/2
├ ○ /ssg
├ ƒ /ssr
└ /strict/[id]
└ ● /strict/1
○ (Static) prerendered as static content
● (SSG) prerendered as static HTML (uses generateStaticParams)
ƒ (Dynamic) server-rendered on demand
読み取れることは3つあります。ISRのページは記号上は○(静的)で、Revalidate列に期限が付くだけです。CSRのページも○になります。サーバーで作られるのは「読み込み中」の外枠だけで、本文はブラウザで描かれるからです。そして/posts/3のようにビルド時に作らなかったパス(ISG)は、この一覧には出てきません。
x-nextjs-cacheヘッダーで見るISRとISGの挙動
サーバーを起動してcurlでアクセスし、レスポンスヘッダーのx-nextjs-cacheとページに出る生成時刻を記録しました。x-nextjs-cacheの値はNext.jsのISRガイドで、HIT(キャッシュから返した)・STALE(キャッシュを返しつつ裏で再生成中)・MISS(キャッシュに無く今作った)・REVALIDATED(オンデマンド再検証で作り直した)と定義されています。
| アクセス | x-nextjs-cache | ページの生成時刻 |
|---|---|---|
| /isr(期限10秒以内) | HIT | 11:47:04(ビルド時) |
| /isr(10秒経過後の1回目) | STALE | 11:47:04(古い版) |
| /isr(再生成の完了後) | HIT | 11:47:21(再生成された版) |
| /posts/3(未生成・1回目) | MISS | 11:47:14(今作った) |
| /posts/3(2回目) | HIT | 11:47:14(保存された版) |
| /ssr(2回) | なし | 11:47:14、11:47:16(毎回変わる) |
ISRの期限切れ直後のアクセスでは古い版が返る、という点が数字で確認できます。期限を10秒にしても、10秒経てば最新になるわけではありません。「期限切れの後に1人がアクセスし、その裏で作り直しが終わった後」に最新になります。アクセスが少ないページでは、古い版が何日も表示され続けることがあります。
Cache-Controlヘッダーにも違いが出ます。SSGとISGのページはs-maxage=31536000(1年)、ISRのページはs-maxage=10, stale-while-revalidate=31535990、SSRのページはprivate, no-cache, no-store, max-age=0, must-revalidateでした。CDNを前に置く場合、CDNはこの値に従ってキャッシュします。
App RouterでdynamicParams = falseを付けると、generateStaticParamsに無いパスは404になりました。これが純粋なSSGで、ISGを止めたい(想定外のURLでページを作らせたくない)場合に使います。
オンデマンド再検証の挙動:次のアクセスでMISSと再生成
期限ではなく、CMSの更新をきっかけに作り直す方法もあります。App RouterではrevalidatePath(パス単位)かrevalidateTag(データのタグ単位)を呼びます。Route HandlerからrevalidatePath('/isr')を呼んだ直後に/isrへアクセスすると、x-nextjs-cacheはSTALEではなくMISSになり、その場で作った新しい版が返りました。時間で期限切れになったときと違い、古い版は返りません。ガイドが挙げるREVALIDATEDという値は、今回の計測では一度も出ませんでした。
公式ガイドの注意書きには、作り直しの範囲にかかわる点が2つあります。既定のキャッシュはファイルシステムにあり、サーバーを複数台並べるとオンデマンド再検証は呼び出しを受けた1台にしか効きません。また、ISRはoutput: 'export'の静的エクスポートでは使えず、Node.jsサーバーかDockerコンテナ、対応するホスティングで動かす必要があります。
Next.js App Routerでの5方式の書き分け
App Routerには「SSRを使う」「ISRを使う」という設定項目はありません。ページの書き方からNext.jsが方式を決めます。今回の実測に使ったファイルをそのまま載せます(package.jsonは"type": "module"、依存はnext 16.4.3・react 19.3.1・react-dom 19.3.1のみ)。
// app/layout.js
// ルートレイアウト:App Routerでは必須(無いとnext buildが失敗する)
export default function RootLayout({ children }) {
return (<html lang="ja"><body>{children}</body></html>);
}
// app/ssg/page.js
// SSG:何も指定しない(ビルド時に1回だけ作る)
export default function Page() {
return <p>SSG generated at {new Date().toISOString()}</p>;
}
// app/isr/page.js
// ISR:有効期限を秒で指定する(実測では10と3600で計測)
export const revalidate = 10;
export default function Page() {
return <p>ISR generated at {new Date().toISOString()}</p>;
}
// app/ssr/page.js
// SSR:connection()でリクエストを待つとページ全体が動的になる
import { connection } from 'next/server';
export default async function Page() {
await connection();
return <p>SSR generated at {new Date().toISOString()}</p>;
}
// app/csr/page.js
// CSR:use clientで宣言し、表示をuseEffectの後に回す
'use client';
import { useEffect, useState } from 'react';
export default function Page() {
const [t, setT] = useState(null);
useEffect(() => { setT(new Date().toISOString()); }, []);
return <p>CSR rendered at {t ?? 'loading...'}</p>;
}
// app/posts/[id]/page.js
// SSG+ISG:ビルド時に作るパスを返し、残りは初回アクセスで作る
export function generateStaticParams() {
return [{ id: '1' }, { id: '2' }];
}
export default async function Page({ params }) {
const { id } = await params;
return <p>post {id} generated at {new Date().toISOString()}</p>;
}
// app/strict/[id]/page.js
// ISGを止める:dynamicParams = false で未知のパスを404にする
export const dynamicParams = false;
export function generateStaticParams() {
return [{ id: '1' }];
}
export default async function Page({ params }) {
const { id } = await params;
return <p>strict {id}</p>;
}
// app/api/revalidate/route.js
// オンデマンド再検証:呼ばれたら/isrを作り直す対象にする
import { revalidatePath } from 'next/cache';
export async function POST() {
revalidatePath('/isr');
return Response.json({ revalidated: true });
}
Next.js 16でcacheComponentsを有効にすると、revalidateやdynamicParamsといったroute segment configは使えなくなり、'use cache'とcacheLifeで寿命を書く方式に変わります(route segment configのリファレンス)。上のコードはcacheComponentsを有効にしていない既定の構成での書き方です。
Pages Routerでは方式ごとに関数が分かれていました。getServerSidePropsがSSR、getStaticPropsがSSG、getStaticPropsの戻り値にrevalidateを足すとISR、getStaticPathsのfallback: true/'blocking'がISGです。cookies()などで静的化が外れる条件やcacheComponentsでの書き方はNext.jsのレンダリング方式|SSG・ISR・SSR・CSRの違いとApp Routerでの選び方で扱っています。
SEO・表示速度・サーバー負荷での違い
SEO:CSRのレンダリング待ちと初期HTMLの本文の有無
GoogleはJavaScriptを実行してページを描画するので、CSRのページでもインデックスされます。ただしGoogle検索セントラルのJavaScript SEOの基本が説明するとおり、処理はクロール・レンダリング・インデックスの3段階に分かれ、レンダリングは後回しになることがあります。実測でもCSRのページの初期HTMLには「loading…」しか入っておらず、本文はJavaScriptが動くまで存在しません。JavaScriptを実行しないSNSのリンクプレビューや、GPTBot・ClaudeBotのようにJavaScriptを実行しないAIのクローラーには、CSRのページの本文は届きません(Vercelの2024年12月の調査)。
SSR・SSG・ISG・ISRはいずれも初期HTMLに本文が入るので、検索エンジンに対する差はほぼありません。SEOのためにSSRを選ぶ必要はなく、SSGやISRで足ります。
表示速度とサーバー負荷:HTMLの生成回数による差
速さと負荷は「1ページを何回作るか」で決まります。SSGは1回、ISGは初回アクセスの1回、ISRは期限ごとに1回、SSRはアクセスのたびに作ります。CSRはサーバーの負荷は小さいものの、表示までの時間を利用者の端末に払わせる方式です。
見落としやすいのはSSRとCSRの組み合わせで、サーバーで作ったHTMLとブラウザでの描画が食い違うとハイドレーションエラーになります。原因と対処はハイドレーションエラー(Hydration Error)とは?原因とReact / Next.jsでの対処法を解説を参照してください。
ページ単位の方式の選び方と失敗パターン
1つのサイトを1つの方式で統一する必要はありません。Next.jsもNuxtもAstroも、ページ(ルート)ごとに方式を変えられます。迷ったら、次の順に当てはめてください。
| ページの性質 | 選ぶ方式 | 例 |
|---|---|---|
| 公開後ほぼ変わらない | SSG | 会社概要、ドキュメント |
| 件数が多く全部はビルドできない | SSG+ISG | 商品詳細、求人詳細 |
| 定期的に内容が変わる | ISR(+オンデマンド再検証) | 記事一覧、価格表 |
| 利用者ごとに中身が違う・常に最新が必要 | SSR | マイページ、在庫数 |
| ログイン後の操作画面で検索流入が要らない | CSR | 管理画面、ダッシュボード |
よくある失敗は次の4つです。
- ISRの期限を1秒にする:公式ガイドも1秒より1時間のような長い期限を勧め、正確さが必要ならオンデマンド再検証、常に最新が必要ならSSRに切り替えるよう書いています。短い期限は作り直しの回数を増やすだけです。
- 静的ホスティングにISRのサイトを置く:S3やGitHub Pagesに
output: 'export'で書き出すと、ISRとISG(dynamicParams: true)は使えません。ホスティング先を先に決めてから方式を選びます。 - 複数台構成でオンデマンド再検証が一部にしか効かない:コンテナを2台以上動かすなら、共有キャッシュ(cacheHandler)を用意します。
- 検索流入が要るページをCSRにする:Googleには届いても、SNSのプレビューや、GPTBot・ClaudeBotのようにJavaScriptを実行しないAIのクローラーには本文が届きません。
業務システムなら、公開ページはSSGかISR、ログイン後はSSRかCSRという分け方が上の表の基本形になります。方式の選定から実装までまとめて相談したい場合は、業務用・Webアプリ開発の支援内容もご覧ください。
Nuxt・Astro・Gatsbyでの呼び名と設定
ISRやISGはNext.js発の言葉ですが、同じ考え方は他のフレームワークにもあり、名前と設定方法が違います。
| フレームワーク | SSG | SSR | ISR・ISG相当 | CSR |
|---|---|---|---|---|
| Next.js | 既定(静的化) | 動的API・connection() | revalidate/dynamicParams | ‘use client’+useEffect |
| Nuxt | routeRules prerender | 既定 | routeRules isr・swr | routeRules ssr: false |
| Astro | 既定(output: static) | prerender = false | Vercelアダプターのisr | client:only |
| Gatsby | 既定 | getServerData | DSG(defer: true) | ブラウザでのデータ取得 |
Nuxtは何も指定しなければSSR(公式の呼び名はユニバーサルレンダリング)で、Rendering ModesのドキュメントにあるとおりrouteRulesでルートごとに方式を変えます。swrはサーバーかリバースプロキシに応答をキャッシュし、期限後も古い応答を返しながら裏で作り直す設定で、Next.jsのISRに当たります。isrはそれにCDNのキャッシュを足したもので、公式が対応先として挙げているのはNetlifyとVercelだけです。isr: trueと期限を付けずに書くと、次のデプロイまでCDNに残ります。
Astroはoutput: 'static'が既定で、全ページをビルド時に作ります。リクエスト時に描画したいページだけアダプターを入れたうえでexport const prerender = falseを書きます。ISRに当たる機能は本体には無く、@astrojs/vercel(7.2.0以降)のisr設定で、オンデマンド描画したページを初回リクエスト後にキャッシュします。
GatsbyのDSG(Deferred Static Generation)は、createPageにdefer: trueを渡したページをビルドから外し、最初のリクエストで作る仕組みで、ISGとほぼ同じ考え方です。公式リファレンスによれば、2回目以降は初回に作ったHTMLとJSONを使い回し、動かすにはNode.jsサーバーが必要です。
よくある質問
SSRは何の略ですか?
Server-Side Renderingの略で、日本語ではサーバーサイドレンダリングと呼びます。リクエストのたびにサーバーでHTMLを作る方式です。ゲームのレアリティを表す「SSR」とは無関係です。
SSGとISRの違いは何ですか?
公開後に作り直すかどうかです。SSGはビルド時に作ったHTMLを再ビルドまで使い続け、ISRは期限切れやオンデマンド再検証をきっかけに、そのページだけを作り直します。
SSGとISGの違いは何ですか?
ページを作るタイミングです。SSGは全ページをビルド時に作り、ISGはビルド時に作らなかったページを最初のアクセスで作って保存します。Next.jsではfallbackやdynamicParamsの挙動に当たり、現行の公式ドキュメントは「ISG」という方式名を使っていません。
CSRはSEOに不利ですか?
Googleには評価されますが、レンダリング待ちが入るぶん不確実です。本文の入ったHTMLを返すSSG・ISR・SSRのほうが確実で、JavaScriptを実行しないSNSやAIのクローラーにも本文が届きます。
ISRは静的ホスティング(S3やGitHub Pages)で使えますか?
使えません。Next.jsのドキュメントは、ISRを静的エクスポートの非対応機能に挙げています。ISRにはNode.jsサーバー、Dockerコンテナ、または対応ホスティングが必要です。