CSR・SSR・SSG
- なぜ生まれた?
- ブラウザだけで描く SPA は、検索エンジンに空のページを返し、表示まで白い画面が続いた。
- 何を解決した?
- 同じ JavaScript をサーバーでも動かして最初の HTML を返し、変わらないページは前もって作った。
- 何を残した?
- HTML が見えても JavaScript が動くまで操作に応えず、全ページを作る手間も残った。
- 登場
- 状態
- 現役
CSR・SSR・SSG という考え方が無かったころ
Section titled “CSR・SSR・SSG という考え方が無かったころ”HTML はサーバーが作るものだった
Section titled “HTML はサーバーが作るものだった”2013年、Airbnb のエンジニアの Spike Brehm は、Web のはじまりからの閲覧の仕組みをこう振り返っています。
“a web browser would request a particular page …, causing a server somewhere on the Internet to generate an HTML page and send it back over the wire.” (ブラウザが特定のページを求めると、インターネットのどこかのサーバーが HTML のページを作り、回線越しに送り返す)
CGI のプログラムも PHP のページも、この形で HTML をサーバーで組み立てていました。HTML をどこで作るかは、選ぶものではありませんでした。 その前提を崩したのが SPA です。画面を組み立てる仕事がブラウザの JavaScript に移り、はじめて「どこで描くか」が問いになりました。
一度ブラウザに移した描画を、なぜサーバーに戻したのか
Section titled “一度ブラウザに移した描画を、なぜサーバーに戻したのか”Brehm によれば、Airbnb は2011年にモバイル向けの Web サイトで SPA を作りはじめました。
“We dove into the single-page app world in 2011 with our mobile web site.” (2011年、モバイルの Web サイトで single-page app の世界に飛び込んだ)
使ったのは Backbone.js です。Brehm は困りごとを2つ挙げています。 1つ目は検索エンジンで、“An application that can only run in the client-side cannot serve HTML to crawlers, so it will have poor SEO by default.”(クライアントでしか動かないアプリケーションはクローラーに HTML を渡せないので、そのままでは SEO が弱い)。 2つ目は最初の表示で、描画をブラウザの JavaScript に任せると、利用者は中身が出るまでの数秒間、白いページか読み込み中の印を見ることになります。 加えて Brehm は、日付の書式やフォームの検証、URL の振り分けがサーバーとブラウザで “often in different languages”(しばしば違う言語で)二重に書かれがちだと書いています。Airbnb の本体は Rails のアプリケーションでした。
“Some developers, myself included, feel bitten by this approach” (私も含め、この作り方に痛い目を見たと感じている開発者がいる)
その間の2012年には、Twitter も描画をサーバーに戻していました(経緯は SPA の記事にあります)。Brehm はこの例を引き、体感の読み込み時間が5分の1になったという Twitter の発表を紹介しています。
動かし続けなくてよいサイト
Section titled “動かし続けなくてよいサイト”前もってファイルを作る側の話は、もっと早く、別の場所で始まっていました。 2008年、Tom Preston-Werner は WordPress のような込み入ったブログのエンジンに疲れ、テンプレートの手入れやコメントの管理より記事を書くことに時間を使いたいと考えていました。
“a static site would be preferable to a dynamic site that required ongoing maintenance.” (手入れを続けなければならない動的なサイトより、静的なサイトのほうが望ましい)
CSR・SSR・SSG という考え方
Section titled “CSR・SSR・SSG という考え方”同じコードが、ブラウザでもサーバーでも動く
Section titled “同じコードが、ブラウザでもサーバーでも動く”2011年10月17日、Node.js のホスティング会社 Nodejitsu のブログに、Charlie Robbins の「Scaling Isomorphic Javascript Code」が載りました。
“Javascript is now an isomorphic language. By isomorphic we mean that any given line of code (with notable exceptions) can execute both on the client and the server.” (JavaScript はいまや isomorphic な言語だ。isomorphic とは、どの行のコードも(目立った例外を除けば)クライアントでもサーバーでも動くという意味だ)
この記事は、この日を登場としています。同じコードをブラウザとサーバーの両方で動かす、という前提に名前を付けた文書のうち、日付まで確かめられたもっとも早いものだからです。 ただし Robbins の主題は、Rails や Django のような MVC に代わるコードの組み立て方で、描画をどこで行うかではありません。描画の場所を選ぶ話としてこの語を広めたのは、2年後の Airbnb でした。静的なサイトの生成は、名前が付く前の2008年から行われています。
Airbnb が「新旧の混ぜ合わせ」と呼んだもの
Section titled “Airbnb が「新旧の混ぜ合わせ」と呼んだもの”2013年11月11日、Brehm は「Isomorphic JavaScript: The Future of Web Apps」を書きました。
“we want to serve fully-formed HTML from the server for performance and SEO, but we want the speed and flexibility of client-side application logic.” (性能と SEO のためにサーバーから完成した HTML を返したい。しかし、クライアントで動くアプリケーションの速さと柔軟さも欲しい)
Brehm はこれを “a hybrid of the new and old approaches”(新旧の作り方の混ぜ合わせ)と呼び、“This idea isn’t new”(この考えは新しくない)として、2011年の Nodejitsu を先に挙げています。 最初の HTML はサーバーで作り、その後の画面の切り替えはブラウザで行う。 これが、のちに SSR と呼ばれる作り方の中心です。
検索エンジンの側では、2015年10月14日に Google が、JavaScript をおおむねブラウザと同じように描画できると書きました。ただし同じ記事は “websites shouldn’t pre-render pages only for Google”(Google のためだけにページを事前に描画すべきではない)とし、事前に描画するなら利用者のための性能が理由だろう、としています。最初の HTML をどこで作るかは、利用者の待ち時間の問題として残りました。
SSR は昔の PHP・CGI のサーバー描画と何が違うのか
Section titled “SSR は昔の PHP・CGI のサーバー描画と何が違うのか”PHP や CGI と直接比べた文は、今回の一次資料には見つけられませんでした。資料の言葉から言える違いは2つです。 1つ目は、サーバーとブラウザで同じコードが動くことです。Robbins の定義のとおり、同じ JavaScript の部品がサーバーで HTML を作り、ブラウザでも画面を作ります。Brehm が困っていた、2つの言語での二重化を減らすのが狙いでした。 2つ目は、HTML を返したあと、ブラウザの JavaScript が引き継ぐことです。web.dev の記事(2026年1月の更新版)は、サーバーが HTML に描画用のデータと JavaScript を埋め込み、ブラウザで “picks up by rendering again on the client”(もう一度描画して引き継ぐ)と説明しています。
| 昔のサーバー描画 | SPA(CSR) | SSR(isomorphic) | 静的生成(SSG) | |
|---|---|---|---|---|
| 最初の HTML を作る場所 | サーバー | ブラウザ | サーバー | ビルドの環境 |
| 作るとき | リクエストごと | ページを開いたあと | リクエストごと | ビルドのとき |
| その後の画面の切り替え | 新しいページを読み直す | ブラウザの JavaScript | ブラウザの JavaScript | ページによる |
| 画面を作るコードの言語 | サーバーの言語(PHP・Perl など) | ブラウザの JavaScript | サーバーとブラウザで同じ JavaScript | 生成の道具による |
「CSR」「SSR」「SSG」という呼び名はいつ、誰が使い始めたのか
Section titled “「CSR」「SSR」「SSG」という呼び名はいつ、誰が使い始めたのか”略語の初出は、一次資料では確かめられませんでした。確かめられた使われ方を並べます。
| 年 | 呼び名 | 誰が・どこで |
|---|---|---|
| 2011 | isomorphic | Charlie Robbins(Nodejitsu) |
| 2013 | server-side rendering | React 0.4.0 の変更履歴(“Improved server-side rendering APIs”) |
| 2013 | Isomorphic JavaScript | Spike Brehm(Airbnb) |
| 2015 | Universal JavaScript | Michael Jackson |
| 2016 | Jamstack | Matt Biilmann の講演で広まる(jamstack.org による) |
| 2019 | SSR・CSR・Static rendering・Prerendering | Addy Osmani・Jason Miller(web.dev) |
| 2020 | SSG・SSR | Next.js 9.3 の発表 |
Jackson は、React の講習で isomorphic の意味をよく聞かれ、universal なら伝わったと書いています(本人は逸話だと断っています)。Jamstack の語は、Biilmann 本人が対談で “it was maybe not even me that actually coined the term”(作ったのは私ではないかもしれない)と話しています。
2019年2月6日の web.dev の「Rendering on the Web」は、SSR を “Rendering an app on the server to send HTML, rather than JavaScript, to the client.”(JavaScript ではなく HTML をクライアントに送るために、サーバーでアプリを描画すること)、CSR を “Rendering an app in a browser, using JavaScript to modify the DOM.”(JavaScript で DOM を書き換え、ブラウザでアプリを描画すること)と定義しています(引用は2026年1月の更新版)。 静的な描画は “producing a separate HTML file for each URL ahead of time”(URL ごとに別の HTML ファイルを前もって作ること)で、呼び名は Static rendering です。SSG の略語は、2020年3月9日の Next.js 9.3 の発表が “Static generation (SSG) or server-side rendering (SSR)” と並べて使っています。 名前は isomorphic から universal へ、そして描く場所とときを指す CSR・SSR・SSG へと移っていきました。
CSR・SSR・SSG を実装した技術
Section titled “CSR・SSR・SSG を実装した技術”Rendr:Backbone のアプリを Node.js でも描く
Section titled “Rendr:Backbone のアプリを Node.js でも描く”Airbnb は、モバイルの Web アプリを作り直すために Rendr を作りました。Backbone.js と Handlebars.js で書いたアプリを、Node.js の Express の上でも描画するライブラリです。 Brehm によれば最初の紹介は2013年1月のブログで、4月10日にオープンソースにしています。反響から、多くの開発者が同じ痛みを抱えていたとわかったと書いています。
“poor pageload performance, lack of SEO, duplication of application logic, and context switching between languages.” (遅いページの読み込み、SEO の欠如、アプリケーションの処理の重複、言語の切り替え)
同じ年の HTML5DevConf では、ほかに2人がサーバー側で Backbone を動かす試作を発表していました。クライアントの Backbone のアプリに困った開発者たちが、別々に同じ答えにたどり着いていたことになります。
React のサーバー描画の API
Section titled “React のサーバー描画の API”React は2013年5月29日の 0.3.0 で公開されました。7月17日の 0.4.0 の変更履歴には “Improved server-side rendering APIs”(サーバー側で描画する API の改良)とあり、React.renderComponentToString(<component>, callback) でサーバーで HTML を作ってブラウザに送れる、と書かれています。
その後、2014年2月20日の 0.9.0 で HTML の文字列を同期的に返すようになり、2014年10月28日の 0.12.0 で React.renderToString に名前が変わります。
コードで見る違い
Section titled “コードで見る違い”ブラウザだけで描く形と、React 0.12 でサーバーでも描く形を比べます。どちらもこの記事のための作例で、App は画面の部品、bundle.js は Browserify などでまとめたブラウザ用のファイルとして省いています。
<!DOCTYPE html><div id="root"></div> <!-- サーバーが返すのはここまで。中は空 --><script src="/bundle.js"></script>var http = require('http');var React = require('react');var App = require('./app'); // ブラウザと同じ部品
http.createServer(function (req, res) { var html = React.renderToString( React.createElement(App, { path: req.url }) ); res.end('<!DOCTYPE html><div id="root">' + html + '</div>' + '<script src="/bundle.js"></script>');}).listen(3000);CSR だけの形では、クローラーにも利用者にも、最初に届くのは空の div です。
SSR の形なら、同じ App で作った中身入りの HTML が最初に届きます。 その後はブラウザの bundle.js が同じ部品を描き、画面の切り替えを受け持ちます。
静的なファイルを作る SSG は、なぜ改めて広まったのか
Section titled “静的なファイルを作る SSG は、なぜ改めて広まったのか”2008年11月17日、Preston-Werner は Jekyll を発表しました。
“Jekyll is a simple, blog aware, static site generator.” (Jekyll は、ブログを理解する、単純な静的サイトの生成器だ)
テンプレートのディレクトリを Textile と Liquid の変換に通し、Apache などでそのまま配れる静的なサイト一式を作ります。 1か月後の2008年12月18日に始まった GitHub Pages は、リポジトリに push した中身を公開する仕組みで、Jekyll の作者自身が “we pipe every Pages-bound repo/branch through Jekyll”(Pages 用のリポジトリとブランチはすべて Jekyll に通す)と書いています。
SSR より前からあった静的な生成が、2010年代の後半に改めて取り上げられた理由として、資料からは3つが挙がります。
- 速さと配りやすさ: web.dev は、静的な描画は HTML をその場で作らないので TTFB(最初の1バイトが届くまでの時間)が安定して速く、複数の CDN に置けると書いています。
- 呼び名: 2016年に広まった Jamstack が、画面の層をデータや処理から切り離す作り方に名前を与えました(jamstack.org の説明)。
- ページごとの選択: Next.js 9.3 は、データが要るページもビルド時に作れるようにし、例に CMS で書くマーケティングのページやブログを挙げました。発表の “Next.js is the first hybrid framework”(最初のハイブリッドなフレームワーク)は作者たち自身の評価です。
import { loadPosts } from '../lib/cms'; // データを取る関数(省略)
export default function Posts({ posts }) { return <ul>{posts.map((p) => <li key={p.id}>{p.title}</li>)}</ul>;}
// ビルドのときに呼ばれる(静的生成)export async function getStaticProps() { return { props: { posts: await loadPosts() } };}// リクエストのたびにサーバーで呼ばれる(SSR)export async function getServerSideProps(context) { return { props: { posts: await loadPosts() } };}部品は同じで、違うのは export する関数の名前だけです。SSG にするか SSR にするかを、ページ単位で書き分けられるようになりました。
残した課題と、次に来たもの
Section titled “残した課題と、次に来たもの”HTML が見えても、まだ押せない
Section titled “HTML が見えても、まだ押せない”web.dev は、サーバーで描いてブラウザで引き継ぐ形の弱点をこう書いています。
“The primary downside of server-side rendering with rehydration is that it can have a significant negative impact on TBT and INP, even if it improves FCP.” (サーバー描画と rehydration の組み合わせの主な弱点は、FCP は良くなっても、TBT と INP を大きく悪くしうることだ)
画面は読み込み済みに見えても、部品の JavaScript が動いてイベントがつながるまでは入力に応えられない、とも書いています。この負担は、ハイドレーションの問題として論じられていきます。
すべての URL を前もって作る
Section titled “すべての URL を前もって作る”静的な生成にも弱点があります。web.dev は “it must generate individual HTML files for every possible URL”(ありうるすべての URL について HTML ファイルを作らなければならない)と書き、URL を前もって予測できないときや、ページの数がとても多いサイトでは難しいとしています。 Next.js は2020年7月27日の 9.5 で、公開後にページを裏で作り直す Incremental Static Regeneration を安定版にしました。
次に来たもの
Section titled “次に来たもの”React は2022年3月29日の 18.0.0 で、ストリームで HTML を送る renderToPipeableStream と renderToReadableStream を加え、“The existing renderToString method keeps working but is discouraged.”(いまの renderToString は動くが、勧めない)と書きました。
2024年12月5日の 19.0.0 は、静的なサイトの生成のための prerender と prerenderToNodeStream を加えています。
ハイドレーションとアイランドアーキテクチャ、Next.js(2016年)と Gatsby の誕生は、それぞれ別の記事で扱います。
2026年10月時点の立ち位置
Section titled “2026年10月時点の立ち位置”SSR や SSG で作られたサイトがどれだけあるかを直接示す数字は、見つけられませんでした。 近い数字を、何の割合かを添えて並べます。
| 指標 | 数字 | 出典 |
|---|---|---|
| React が見つかったページ(デスクトップ・モバイルとも) | 10% | Web Almanac 2024(データは2024年) |
| Next.js を使っている回答者 | 59% | State of JS 2025(InfoQ の報道による) |
| React を使っている回答者 | 83.6% | 同上 |
Web Almanac の数字はページの割合で、React を使うページが SSR か CSR かはわかりません。State of JS の数字は調査に答えた開発者の割合で、サイトの割合ではありません。InfoQ によれば、同じ調査で Next.js への好意的な評価は 21%、否定的な評価は 17% でした。
Next.js は2026年10月23日に v16.4.3 を出しています(GitHub のリリース)。 web.dev の記事は2026年1月5日に更新され、ロジックと描画をどこで行うかを Web の開発者の中心の判断の1つとしたうえで、全体を rehydration する作りより SSR か静的な描画を検討し、まずボトルネックを計測するよう勧めています。どれか1つが正解になったのではなく、計測して選ぶものとして説明されています。
- SPA で描画をブラウザに移すと、Airbnb のモバイル Web では検索エンジンに空のページを返し、表示まで白い画面が続きました。
- 2011年10月17日に Robbins が両方で動くコードを isomorphic と呼び、2013年に Brehm が「サーバーで最初の HTML を作り、ブラウザで引き継ぐ」作り方として広めました。
- 静的な生成は名前が付く前の2008年に Jekyll で始まり、2019年の web.dev の用語の整理、2020年の Next.js 9.3 のページごとの選択へ続きます。
- HTML が見えても JavaScript が動くまで操作に応えない問題と、全 URL を前もって作る手間が残り、ハイドレーションやアイランドの議論につながりました。
- 2026年10月時点で SSR・SSG のサイトの割合を示す数字は無く、web.dev は計測したうえで SSR や静的な描画を検討するよう勧めています。
年表
Tom Preston-Werner が、静的なサイトを生成する Jekyll を発表する tom.preston-werner.com
GitHub Pages が始まり、Pages 用のリポジトリを Jekyll に通して配信する web.archive.org
Nodejitsu の Charlie Robbins が、JavaScript を「isomorphic な言語」と呼ぶ web.archive.org
Airbnb が、Backbone.js のアプリをブラウザと Node.js の両方で描く Rendr をオープンソースにする medium.com
React 0.4.0 が、サーバーで HTML を作る `React.renderComponentToString` を改良する github.com
Airbnb の Spike Brehm が「Isomorphic JavaScript: The Future of Web Apps」を書く medium.com
Michael Jackson が、isomorphic に代えて「Universal JavaScript」と呼ぶことを提案する medium.com
Google が、2009年の AJAX クロールの仕組みを勧めるのをやめる webmasters.googleblog.com
web.dev の「Rendering on the Web」が、SSR・CSR・静的な描画などの用語を定義する web.dev
Next.js 9.3 が、ページごとに静的生成(getStaticProps)とリクエストごとの描画(getServerSideProps)を選べるようにする nextjs.org
系譜
前
- 課題SPA2003年5月16日
- 土台Node.js準備中
この技術が出てくる物語
出典
- 一次Scaling Isomorphic Javascript Code(Charlie Robbins, blog.nodejitsu.com, 2011-10-17) blog.nodejitsu.com 保存版
- 一次Isomorphic JavaScript: The Future of Web Apps(Spike Brehm, Airbnb Engineering, 2013-11-11) medium.com 保存版
- 一次Rendr: Run your Backbone apps in the browser and Node(Spike Brehm, Airbnb Engineering, 2013-04-10) medium.com 保存版
- 一次Universal JavaScript(Michael Jackson, 2015-06-08) medium.com 保存版
- 一次Rendering on the Web(Addy Osmani・Jason Miller, web.dev, 2019-02-06 公開、2026-01-05 更新) web.dev
- 一次React CHANGELOG.md github.com
- 一次Deprecating our AJAX crawling scheme(Official Google Webmaster Central Blog, 2015-10-14) webmasters.googleblog.com 保存版
- 一次Blogging Like a Hacker(Tom Preston-Werner, 2008-11-17) tom.preston-werner.com
- 一次GitHub Pages(The GitHub Blog, 2008-12-18) github.com 保存版
- 一次Next.js 9.3(Next.js Blog, 2020-03-09) nextjs.org
- 一次Next.js 9.5(Next.js Blog, 2020-07-27) nextjs.org
- 一次What is Jamstack?(jamstack.org) jamstack.org
- 一次Jamstack Radio Ep. #2, The Jamstack Origin Story(Heavybit) heavybit.com
- 二次Web Almanac 2024 JavaScript(HTTP Archive) almanac.httparchive.org
- 二次State of JavaScript 2025 の調査結果の報道(Daniel Curtis, InfoQ, 2026-03-20) infoq.com