Next.js SSR vs SSG vs ISR:レンダリング戦略の選び方ガイド
「なぜトップページの読み込みに 3 秒もかかるんだ?」上司が Chrome DevTools のウォーターフォールを睨み、赤く伸びた TTFB のバーを指差しました。あのとき初めて、最初からレンダリング戦略を選び間違えていたのかもしれないと気づきました。
これは特別な話ではありません。Next.js の GitHub Issues でも、毎日のように「SSR と SSG、どっち?」「ISR を設定したのに効かない」という質問が上がります。ドキュメントは読んだはずなのに、具体的なプロジェクトではどれを選べばいいか迷う——以前の私もそうでした。
こんな悩み、ありませんか?
- SSR にしたら初期表示が遅くてイライラする
- SSG にしたら、ちょっとした更新でもサイト全体を再ビルドする
- ISR は良さそうに見えるのに、設定しても全然動かない
この 3 つの戦略に「最強」はありません。あるのは「最適かどうか」だけです。本記事では、どの場面でどれを使うべきか、そしてよくある落とし穴の避け方を整理します。
まず押さえる:3 つのレンダリング戦略とは
選び方の前に、3 つの概念をできるだけ素直な言葉で整理しましょう。
SSG(静的サイト生成):作り置きのお弁当
お弁当屋を想像してください。朝に 100 個作ってカウンターに並べ、客が来たら渡すだけ。これが SSG です。
具体的には:
- いつ生成するか:
next build実行時に、全ページの HTML を事前生成 - ユーザーアクセス時:CDN が事前生成 HTML を返す。非常に速い
- 向いている場面:内容があまり変わらないページ。企業サイト、製品紹介、ブログ記事など
メリット:
- 圧倒的に速い。AWS データでは SSG は SSR より 40〜60% 高速
- TTFB(Time To First Byte)は通常 50ms 以内(Vercel 公式計測)
- サーバー負荷はほぼゼロ。トラフィックが増えても安心
- コストが低い。静的ファイルのホスティングは安価
制約もある:
- 内容を更新するには、サイト全体の再ビルドが必要
- ページ数が増えるとビルド時間が長くなる。数千ページで 30 分超も
- パーソナライズ不可。全ユーザーに同じ内容
要するに、SSG は「事前準備」で速度を買う戦略です。
SSR(サーバーサイドレンダリング):注文してから調理
今度は作り置きをやめます。客が注文したものを、その場で調理して渡す。これが SSR です。
具体的には:
- いつ生成するか:ユーザーがリクエストするたびに、サーバーで HTML をリアルタイム生成
- ユーザーアクセス時:DB 参照、API 呼び出し、HTML レンダリングを待ってから返却
- 向いている場面:リアルタイム性やパーソナライズが必要なページ
メリット:
- 内容は常に最新。その瞬間のデータを表示できる
- パーソナライズ可能。Cookie や権限に応じて内容を変えられる
- リクエスト時にしか取れない情報(ヘッダー、クエリパラメータ)にアクセスできる
代償も大きい:
- 遅い。TTFB は通常 200〜500ms(Vercel 公式データ)
- サーバー負荷が高く、トラフィック急増で耐えきれないことも
- サーバーを常時稼働させる必要があり、コストも上がる
実例:ある EC サイトが SSR を採用し、初期表示に 2.3 秒かかっていた。ISR に切り替えて 0.8 秒まで短縮しました。
ISR(インクリメンタル静的再生成):作り置き + 定期更新
賢いやり方です。朝にお弁当を作り、1 時間ごとに入れ替える。客はほとんどの場合、作り置きを受け取るが、中身は古くなりすぎない。これが ISR です。
具体的には:
- 初回ビルド:
next buildで静的 HTML を生成(SSG と同様) - その後の更新:設定した
revalidate時間に応じ、バックグラウンドでページを再生成 - ユーザーアクセス時:多くの場合キャッシュ 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)でテストしている可能性。ISR は本番(next build+next start)でのみ動作 - デプロイ先が非対応? Vercel はネイティブ対応。他プラットフォームは追加設定が必要な場合も
個人的には、ISR が今いちばんよく使う戦略です。SSG と SSR の弱点をうまく埋めてくれます。
判断フロー:どの場面で何を使うか
概念は押さえました。次は実務でいちばん大事な問い——自分のプロジェクトではどれを選ぶか。
焦らなくて大丈夫です。以下のフローに沿って、自分の要件と照らし合わせてみてください。
ステップ 1:3 つの質問に答える
質問 1:内容のパーソナライズは必要か?
ユーザーごとに異なる内容を出す必要があるなら、SSR が第一候補です。
典型例:
- ユーザーダッシュボード(人によってデータが違う)
- プロフィールページ
- カートページ
- 認証後にしか見られないページ
理由はシンプル。パーソナライズされた内容は事前生成できないからです。
質問 2:内容はどれくらいの頻度で更新されるか?
この答えが、SSG か ISR かを決めます。
-
数秒〜数分で更新:SSR
- 株価、スポーツ速報、チャットメッセージなど
- リアルタイム性が最優先なら SSR 一択
-
数分〜数時間で更新:ISR
- ニュース、ブログトップ、商品一覧、EC 在庫など
revalidate: 300(5 分)などで、速さと鮮度を両立
-
ほとんど更新しない、または手動更新:SSG
- 企業サイト、製品紹介、ヘルプドキュメント
- 数週間〜数ヶ月触らないコンテンツ向け
質問 3:トラフィック規模はどのくらいか?
規模はコストと性能の判断材料になります。
-
超高トラフィック(日次 PV 100 万規模):SSG または ISR を優先
- 静的ファイルを CDN で配信でき、コストと性能の両面で有利
- SSR だとサーバー負荷とコストが急増しやすい
-
中〜低トラフィック:3 つとも選択肢
- リアルタイム性が必要なら SSR でも問題ないことも
- ただ、ISR で足りるなら ISR の方が無難なことが多い
ステップ 2:シーン別クイックリファレンス
典型シーンを整理しました。自分のプロジェクトに当てはめてみてください。
SSG 向け:
- ✅ 企業コーポレートサイト
- ✅ 製品紹介、料金ページ
- ✅ マーケティング LP
- ✅ ブログ記事詳細(公開後ほぼ修正しない)
- ✅ 技術ドキュメント、API ドキュメント
- ✅ ヘルプセンター、FAQ
キーワード:静的・公開向け・更新頻度が低い
SSR 向け:
- ✅ SNS タイムライン(Facebook、Twitter 型)
- ✅ 個人ダッシュボード
- ✅ カート、注文ページ
- ✅ リアルタイムデータパネル
- ✅ 検索結果(クエリパラメータ依存)
- ✅ 認証が必要なページ(Cookie 判定)
キーワード:動的・パーソナライズ・リアルタイム
ISR 向け(個人的なおすすめ):
- ✅ ブログトップ、記事一覧(定期的に新記事追加)
- ✅ ニュースサイト
- ✅ EC 商品詳細(価格・在庫が定期更新)
- ✅ 掲示板スレッド(コメント数・いいね数に数分の遅延許容)
- ✅ UGC プラットフォーム(秒単位のリアルタイム不要)
- ✅ 天気予報、為替情報
キーワード:定期更新・遅延許容・高トラフィック
ステップ 3:混合利用が正解
よくある誤解:サイト全体を 1 つの戦略に統一する必要がある、というもの。
実際、多くのプロジェクトは混合構成です:
- トップと商品一覧 → ISR(トラフィック大・定期更新)
- 商品詳細 → SSG(内容安定)または ISR(価格・在庫変動)
- ダッシュボード → SSR(パーソナライズ)
- About、お問い合わせ → SSG(完全静的)
私たちの EC プロジェクトの例:
- トップ(ISR、10 分更新)
- 商品一覧(ISR、5 分更新)
- 商品詳細(ISR、3 分更新。在庫変動のため)
- カート(SSR、リアルタイム必須)
- マイページ(SSR、パーソナライズ)
- About、プライバシーポリシー(SSG、ほぼ不変)
この組み合わせで、性能とリアルタイム性のバランスが取れます。
一言で覚える判断の合言葉
まだ迷うなら、これを覚えてください。
静的なら SSG、リアルタイムなら SSR、定期更新なら ISR
それでも決めきれないときは、まず ISR を試すのが安全です。3 つの中で最もバランスが良く、失敗しにくい選択肢です。
3 大トラブルと解決策
理論は分かっても、現場では必ずハマります。私が踏んだ 3 つの落とし穴を共有します。
トラブル 1:ISR の revalidate が効かない
症状:revalidate: 60 を設定したのに、1 分待っても内容が古いまま。
当時の私:初めて ISR を使ったとき、ここで 2 日間ハマりました。ドキュメントを読み漁り、設定を何度も変えても動かない。
原因は主に 3 つ:
-
開発環境では ISR が動かない
最も多い原因です。
next devでは ISR は動作しません。本番モードでのみ有効です。対処:
# next dev では ISR をテストしない # 必ずビルドしてから起動 npm run build npm run start # その後ページにアクセスして確認 -
デプロイ先が ISR 非対応
すべてのプラットフォームがネイティブ対応しているわけではありません。Vercel は Next.js 公式なので問題少なめ。Netlify などは
@netlify/plugin-nextjsプラグインが必要な場合があります。確認方法:デプロイ先のドキュメントで「Next.js ISR support」を検索。
-
CDN キャッシュが ISR を上書き
Next.js の前段に Cloudflare などの CDN やリバースプロキシがあると、レスポンス全体がキャッシュされ、ISR の更新メカニズムが効かなくなることがあります。
対処:CDN が
Cache-Controlヘッダーを尊重するよう設定するか、ISR ページ向けに CDN キャッシュ時間を短くする。
おすすめ:ISR 設定後は必ず本番環境で検証。console.log(new Date()) でページ生成時刻を出力し、revalidate が効いているか確認しましょう。
トラブル 2:SSR の初期表示が遅すぎる
症状:SSR にしたら、初期表示の白画面が 2〜3 秒続く。
実例:あるプロジェクトで、トップを SSR にしてユーザー情報とおすすめコンテンツを取得。TTFB が 1.2 秒、レンダリング込みで 3 秒待たせる結果に。上司の反応は想像できます。
原因分析:
SSR が遅いのは、多くの場合サーバー側のデータ取得がボトルネックです。
- 外部 API のレイテンシが高い
- DB クエリが遅い(インデックス不足、複雑な JOIN)
- 直列リクエスト(1 つ終わるまで次を待つ)
- サーバー性能不足、またはユーザーから地理的に遠い
解決策は 4 つ:
-
Streaming SSR と Suspense を使う(React 18+)
全データを待ってから返すのではなく、ページの枠組みを先に返し、データ到着後にストリーミング配信します。
// app/dashboard/page.tsx import { Suspense } from 'react'; export default function Dashboard() { return ( <div> <h1>ユーザーダッシュボード</h1> {/* 速く描画できる部分 */} <UserInfo /> {/* 遅いデータは Suspense でラップ */} <Suspense fallback={<div>統計データを読み込み中...</div>}> <SlowStats /> </Suspense> </div> ); }ユーザーはより早く何かを見られるようになり、体感が大きく改善します。
-
データ取得を並列化
複数 API を直列で呼ばず、並列実行に切り替えます。
// ❌ 直列:遅い const user = await getUser(); const posts = await getPosts(user.id); // ✅ 並列:速い const [user, posts] = await Promise.all([ getUser(), getPosts() ]); -
ISR への切り替えを検討
SSR が必要だと思っていても、実は ISR で足りるケースは多いです。
自問してみてください:本当にリアルタイムが必要か? 1 分程度の更新遅延が許容できるなら ISR で十分なことがあります。
前述のトップページは ISR(
revalidate: 60)に変更し、初期表示を 3 秒から 0.7 秒に短縮しました。 -
Edge にデプロイ
Vercel を使っているなら Edge Functions を試せます。SSR 関数をグローバル CDN ノードに配置し、ユーザーに近い場所で実行できます。
// app/api/data/route.ts export const runtime = 'edge'; // この 1 行
トラブル 3:SSG のビルド時間が長すぎる
症状:数千ページあるサイトで next build が 20〜30 分かかり、タイムアウトで失敗する。
よくある場面:EC サイトに 5000 商品、ブログに 3000 記事。SSG だとビルド時に全ページの HTML を生成する必要があります。
なぜ遅いか:
SSG はビルド時に全ページ HTML を生成します。ページが増えるほど時間がかかり、多くのページはそもそも誰もアクセスしない(ロングテール商品、古い記事)ことも。
解決策:
-
fallback 戦略を使う
全ページを一度に生成せず、人気ページだけ事前生成し、他はオンデマンド生成します。
// app/posts/[id]/page.tsx export async function generateStaticParams() { // 人気上位 100 記事だけ返す const posts = await getTopPosts(100); return posts.map(post => ({ id: post.id })); } // 他のページは初回アクセス時に生成 export const dynamicParams = true; -
ISR と組み合わせる
ビルド時はトップと人気ページのみ生成し、他は ISR でオンデマンド生成。
ビルド時間を大幅に短縮でき、ユーザー体感速度も維持できます(キャッシュがあるため)。
-
増分ビルド(Incremental Builds)
Vercel は増分ビルドに対応し、変更があったページだけ再ビルドします。1 記事更新のたびにサイト全体を再ビルドする必要はありません。
他プラットフォームでは自前実装が必要な場合があります。
実際の効果:
2000 記事のブログプロジェクトで、最初は純 SSG でビルドに 15 分かかっていました。変更後:
- ビルド時は最新 50 記事のみ生成
- 他は
dynamicParams = trueでオンデマンド生成 - 全記事ページに ISR(
revalidate: 3600)を適用
ビルド時間は 2 分に短縮。ユーザー体感速度は変わりませんでした。
Next.js 15 の新機能:React Server Components と PPR
ここまで来たら、Next.js 15 がもたらす 2 つの要素にも触れておきましょう。厳密には「レンダリング戦略」そのものではありませんが、ページの組み立て方に大きく影響します。
React Server Components(RSC):コンポーネント単位の SSR
Next.js 13+ の App Router を使っているなら、すでに Server Components を利用しています。
従来の SSR との違いは?
- 従来の SSR:ページ全体をサーバーでレンダリング
- RSC:デフォルトでコンポーネントをサーバーでレンダリング。インタラクションが必要な部分だけクライアントで実行
メリット:
-
JS バンドルが小さくなる
Server Component のコードはクライアントに送られません。Next.js 公式データでは、RSC 導入後クライアント JavaScript ボリュームは 30〜50% 削減可能。
ページ読み込みが速くなり、モバイル端末の負荷も下がります。
-
バックエンドリソースに直接アクセス
Server Component は DB クエリやファイルシステム読み取りができ、わざわざ API エンドポイントを作る必要がありません。
// app/posts/page.tsx // Server Component。DB に直接アクセスできる async function getPosts() { const posts = await db.posts.findMany(); return posts; } export default async function PostsPage() { const posts = await getPosts(); return ( <div> {posts.map(post => ( <PostCard key={post.id} post={post} /> ))} </div> ); }
実践のアドバイス:
- デフォルトは Server Component(App Router のデフォルト)
- インタラクションが必要な部分だけ Client Component(
'use client') - データ取得と静的 UI は Server Component、ボタン・フォーム・アニメーションは Client Component
SEO のメリットを保ちつつ、JS バンドルを小さく保てます。
Partial Prerendering(PPR):静的 + 動的のハイブリッド
PPR は Next.js 15 で導入された実験的機能で、同一ページ内で静的パートと動的パートを混在させられます。
例:EC 商品ページ
- 商品説明、画像 → 静的(ビルド時生成)
- 在庫、価格 → 動的(リクエスト時取得)
PPR なら、静的パートはビルド時に生成し、動的パートだけリクエスト時に計算。速さと鮮度を同時に狙えます。
使い方:
// next.config.js
module.exports = {
experimental: {
ppr: true,
},
};
// app/products/[id]/page.tsx
export const experimental_ppr = true;
export default function ProductPage({ params }) {
return (
<div>
{/* 静的パート:ビルド時生成 */}
<ProductDescription id={params.id} />
{/* 動的パート:リクエスト時生成 */}
<Suspense fallback={<div>読み込み中...</div>}>
<DynamicStock id={params.id} />
</Suspense>
</div>
);
}
大前提:
PPR は現時点では実験的機能です。本番環境での全面採用はおすすめしません。非クリティカルなページで試す程度に留めましょう。
安定版(Next.js 16 あたり?)になれば、かなり強力な選択肢になるはずです。
新機能と SSR/SSG/ISR の組み合わせ
- RSC + SSG:Server Component はデフォルト静的。SSG と相性抜群
- RSC + ISR:Server Component +
revalidate。静的でありつつ定期更新 - RSC + SSR:動的ルートまたは
dynamic = 'force-dynamic'で SSR 化 - PPR:SSG と SSR の究極的な融合と言える
私の理解では、RSC は Next.js のアーキテクチャ刷新、SSG/SSR/ISR はその上のレンダリング戦略。対立ではなく、相補関係です。
まとめ
ここまで読んで、最初の問いに戻りましょう。SSR、SSG、ISR は結局どう選ぶか?
正解は 1 つではありません。プロジェクトごとに要件、トラフィック、予算が違います。ただ、次の 3 点が分かれば選択は難しくありません。
- パーソナライズは必要か? → 必要なら SSR
- 更新頻度は? → リアルタイムなら SSR、定期更新なら ISR、ほぼ不変なら SSG
- トラフィック規模は? → 超高トラフィックなら SSG または ISR を優先
記事冒頭の「なぜこんなに遅いのか」という場面、覚えていますか? あのトップページを SSR から ISR(revalidate: 60)に変更し、初期表示を 3 秒から 0.8 秒に短縮しました。上司も満足、ユーザー体験も改善。
私からのアドバイス:
- 迷ったらまず ISR を試す。3 つの中で最もバランスが良い
- 公開後は Chrome DevTools の Performance パネルで TTFB、FCP などを実測
- ページごとに戦略を変えてよい。教条に縛られない
レンダリング戦略は固定ではありません。プロジェクトが成長し、ユーザーが増え、要件が変われば、戦略も変えて問題ありません。Next.js では切り替えコストも比較的低いです。
本記事が、あなたのプロジェクトでいくつか落とし穴を避ける助けになれば幸いです。実践での経験やハマった話があれば、ぜひコメントで共有してください。
FAQ
SSR、SSG、ISR の核心的な違いは何ですか?
SSG、SSR、ISR はそれぞれいつ使うべきですか?
ISR の revalidate を設定したのに効かないのはなぜですか?
SSR の初期表示が遅い場合はどうすればいいですか?
SSG のビルド時間が長すぎる場合はどうすればいいですか?
異なるレンダリング戦略を混在させられますか?
React Server Components と SSR/SSG/ISR の関係は?
7分で読めます · 公開日: 2025年12月19日 · 更新日: 2026年6月8日
Next.js 完全ガイド
検索からこのページに来た場合は、前後の記事もあわせて読むと同じテーマの理解がかなり早く深まります。
前の記事
Next.js App Router よくある落とし穴と解決策:遠回りを減らす 8 つの実践知見
データ取得からエラー処理まで、Next.js App Router 開発で最もハマりやすい 14 の落とし穴と解決策を総まとめ。Server Components と Client Components の混同、キャッシュ、移行時の問題など、80% のよくあるミスを避ける実践知見を紹介します。
第 11 / 47 記事
次の記事
Next.js Server Actions チュートリアル:フォーム処理とバリデーションのベストプラクティス
Next.js Server Actions のフォーム処理、Zod バリデーション、セキュリティ実践、UX 最適化を実戦例で解説。開発フローを簡素化する新機能をマスターしましょう。
第 13 / 47 記事
関連記事
Next.js App Router 入門ガイド:コア概念と基本操作を解説
Next.js App Router 入門ガイド:コア概念と基本操作を解説
Next.js 15 実践:週末で本番級ブログシステムを構築した方法
Next.js 15 実践:週末で本番級ブログシステムを構築した方法
Next.js Middleware 実践ガイド:パスマッチ、Edge Runtime 制限とよくある落とし穴
コメント
GitHubアカウントでログインしてコメントできます