レンダリング戦略 — CSR / SSR / SSG

Web アプリの「HTML をいつ・どこで生成するか」という設計判断。CSR(クライアント実行時)・SSR(リクエスト時、サーバー)・SSG(ビルド時)の 3 戦略が基本形で、モダンフレームワークの諸機能はこの 3 点間のトレードオフ調整として理解できる。

まず軸を分ける — このテーマの最重要ポイント

「CSR / SPA / SSR / SSG」と並べると 4 つが同列に見えるが、SPA だけ軸が違う。

軸問い選択肢
レンダリング戦略初回の HTML をいつ・どこで作るかCSR / SSR / SSG
アプリケーション構造2 ページ目以降の遷移をどう扱うかSPA / MPA

2 軸は直交していて組み合わせは自由(Next.js = SSR/SSG + SPA 遷移、Rails = SSR + MPA、Create React App = CSR + SPA)。「SPA = CSR」という同一視は、2010 年代前半の古典構成が固定観念化したもの。

3 戦略の比較

CSRSSRSSG
HTML 生成クライアント実行時リクエスト時(サーバー)ビルド時
TTFB速い(空 HTML を返すだけ)サーバー処理時間に依存最速(CDN のファイル配信)
FCP(表示)遅い(JS 実行 + fetch 待ち)速い最速
TTI(操作可能)FCP と同時(だが遅い)hydration 待ちのギャップありhydration 待ち(JS があれば)
SEO / OGP弱い完全対応完全対応
パーソナライズ○(クライアントで自由)◎(リクエスト時情報を使える)×(全員同じ HTML)
更新の反映即時(API 次第)即時リビルドが必要
インフラ静的ホスティングのみレンダリングサーバー必須静的ホスティングのみ
代表Create React App, ViteNext.js, RailsHugo, Astro, Gatsby

指標の意味: TTFB = 最初の 1 バイトが届くまで、FCP = 最初のコンテンツ描画まで、TTI = 操作可能になるまで。

選び方

判断軸は 2 つ: SEO・初回表示は重要か、内容はリクエストごとに変わるか(パーソナライズ・鮮度)。

graph TD
    Q1{"SEO / 初回表示が重要?"} -->|"No(ログイン後ツール)"| CSR["CSR — 管理画面・ダッシュボード"]
    Q1 -->|"Yes"| Q2{"内容はユーザー・時刻で変わる?"}
    Q2 -->|"No(全員同じ)"| SSG["SSG — ブログ・ドキュメント・LP"]
    Q2 -->|"Yes"| SSR["SSR — EC・ニュース・フィード"]

実際のアプリはページごとに性質が違うため、ページ単位で戦略を混ぜるのが現代フレームワークの前提(Next.js はルートごとに static / dynamic を選ぶ)。

歴史 — 振り子ではなく粒度の細分化

時代主流駆動力
〜2000sSSR + MPA — CGI, PHP, RailsWeb は文書だった
2005〜Ajax の衝撃(web2.0)Gmail / Google Maps
2010s 前半CSR + SPA 全盛 — Backbone, Angular, Reactアプリ的 UX、API 分離
2016〜SSR 回帰(isomorphic)— Next.jsCSR の初回表示・SEO の限界
2016〜SSG / Jamstack — Gatsby, Hugo, NetlifyCDN 配信の速さと運用の軽さ
2020sハイブリッド細分化 — ISR, Streaming SSR, RSC, Islandsページ内・ページ単位でトレードオフを最適化

「サーバー → クライアント → サーバー」と振り子が往復しているのではなく、選択の粒度がサイト単位 → ページ単位 → コンポーネント単位へ細かくなっていると読むのが正確。

発展形の位置付け

手法基本戦略何を足すか
ISRSSGリクエスト契機の再生成でリビルドのタイムラグを解消
Streaming SSRSSRHTML をチャンク送信して FCP を前倒し
RSC (React Server Components)SSR/SSGサーバー専用コンポーネントで JS 送信量と hydration を削減
Islands ArchitectureSSG/SSR静的ページの中の interactive な島だけ hydrate
Edge SSRSSRエッジでレンダリングして TTFB を削減

押さえどころ(カード化候補)

関連

Graph