サーバーとブラウザの振り子
1993年4月に公開された NCSA httpd 0.3 は、置いてあるファイルを返すための小さなプログラムでした。 そこから2026年までのあいだに、Web の画面を作る仕事は、サーバーとブラウザのあいだを何度も行き来してきました。
この物語が追うのは、HTML を作る仕事と画面を動かす仕事を、サーバーとブラウザのどちらが受け持つかという1本の軸です。 SPA へ向かった流れを振り子が振れたと書いたのは、2016年に Next.js を発表した ZEIT の公式ブログ自身でした(Next.js の段で引きます)。 ただし、振り子はもとの位置には戻りません。どの段も、前の段が残した困りごとを引き受けたうえで、前とは別の位置に止まっています。
章は、出来事の年の順ではなく、困りごとが受け渡された順に並べています。そのため、Perl が CGI より前に生まれ、SPA の考え方が Ajax という名前より前に書かれているように、年が前後するところがあります。
ページは、サーバーが毎回組み立てる
Section titled “ページは、サーバーが毎回組み立てる”1993年の夏、Web サーバーに検索やデータベースを引かせる方法はサーバーごとに違い、ゲートウェイのプログラムを書いても、サーバーと一緒でなければ人に配れませんでした。
1993年11月、NCSA の Rob McCool が Plexus や CERN のサーバーの作者たちと議論してまとめた CGI は、要求の情報を環境変数と標準入力で渡し、標準出力に書かれたものを返す取り決めです。
同じプログラムが別のサーバーでも動くようになった代わりに、アクセスのたびにプログラムが1回起動し、ページ全体を print で出力する形が残りました。
CGI のプログラムによく使われたのが Perl です。ただし Perl は CGI より6年早く、Web とは関係のない仕事から生まれています。
版の記録で Perl 1.000 は1987年12月18日で、Larry Wall がニュースに置いた問題報告から報告書を作ろうとして、awk ではファイルをまたげなかったことが始まりでした。
CGI に名前が付いたときにはすでに安定版があり、環境変数を $ENV{...} で読み、フォームの文字列を split や s/// で切って置き換える力が、そのまま CGI の仕事に合いました。
一方で、要求のたびに Perl を起動する重さは残り、Web サーバーに Perl を組み込むのも難しかった、と mod_perl の開発者は振り返っています。
その重さに困った1人が Rasmus Lerdorf でした。1994〜95年ごろ、過負荷のサーバーで自分の履歴書のアクセスを数える Perl の CGI を、毎回の fork の負荷を避けるために C で書き直したのが PHP の始まりです。 PHP はふつうの HTML の中に処理を書く形をとり、1996年4月には Apache のモジュールとして CGI を通らずに動くようになりました。 書き方は手軽になっても、要求のたびにサーバーがページ全体を作り直して返すという分担は変わっていません。 ブラウザの仕事は、届いた HTML を表示することでした。
ページを読み直さずに動かしたい
Section titled “ページを読み直さずに動かしたい”サーバーがすべてを作る形では、利用者は何をするにも往復を待ちます。1995年、フォームに入れた郵便番号の桁が足りないことさえ、送信を受けたサーバー側のプログラムでなければ気づけませんでした。 Netscape がブラウザに入れた JavaScript は HTML の中に数行で書け、Navigator 2.0 の手引きの言葉では “Without any network transmission”(ネットワークでの送信なしに)入力を確かめられる言語でした。1995年9月に LiveScript の名で載り、1996年8月には Microsoft も互換の JScript を出します。 ブラウザの中に、処理を書く場所ができました。 ただ、サーバーと話す手段は、まだフォームの送信やリンクで次のページを読み込むことでした。
その手段を変えたのが、のちに Ajax と呼ばれる作り方です。 本人の推定で1998年の終わりごろ、ブラウザでメールを読む Outlook Web Access を作っていた Microsoft の Alex Hopmann が、ページを読み直さずにサーバーと話す部品を作り、XMLHTTP として1999年3月の Internet Explorer 5 に入れました。 2005年2月18日、Jesse James Garrett は Google Suggest や Google Maps に見られるこの作り方を Ajax と名付け、こう問いかけています。
“Once an interface is loaded, why should the user interaction come to a halt every time the application needs something from the server?” (画面がいったん読み込まれたなら、アプリケーションがサーバーから何かを必要とするたびに、利用者の操作が止まらなければならない理由があるだろうか)
サーバーは要るデータだけを返し、ブラウザの JavaScript がページの一部を書き換えます。振り子はブラウザの側へ動きはじめましたが、ページの土台はまだサーバーが作っていました。 その代わり画面の状態を JavaScript が抱えることになり、Hopmann は、アプリケーションが大きくなるほど保守が難しかったと書いています。
画面を組み立てる仕事が、ブラウザへ移る
Section titled “画面を組み立てる仕事が、ブラウザへ移る”2005年、ページに動きを付けるには要素を探して1つずつイベントを付け、そのやり方も Mozilla 系の addEventListener と Internet Explorer の attachEvent で書き分ける必要がありました。
2006年1月に John Resig が発表した jQuery は、$() に CSS のセレクタを渡して要素をまとめて選び、操作を続けて書ける形を約10KBで配りました。
jQuery が手軽にしたのは、サーバーが作ったページの要素を選んで書き換えることです。画面の大部分を JavaScript で組み立てる作り方には、別の道具が現れていきます。
ページを移ることまでブラウザで済ませる考え方は、じつは jQuery や Ajax という名前より前に書かれていました。
2003年5月16日、Netscape の技術者たちは「Inner-Browsing」で、“a model in which all navigation occurs within a single page”(すべてのナビゲーションが1枚のページの中で起きるモデル)を示しています。のちに SPA と呼ばれる作り方です。
これが大きなサイトの形になったのは2010年で、9月の #NewTwitter は画面の描画と処理をすべて利用者のブラウザの JavaScript に任せ、10月には Backbone.js と AngularJS が公開されます。
ここで振り子は、ブラウザの側の端まで振れました。 その代わり、URL の # より後ろはサーバーにも検索エンジンにも届かず、最初の表示は JavaScript が動くまで待つことになりました。
画面をブラウザで組み立てるほど、データが変わるたびに DOM のどこを直すかを書くコードが増えます。Facebook の広告部門でも、社内の BoltJS のコードは “pretty complicated”(かなり込み入った)ものになっていました。 一方、同じ Facebook のサーバー側では PHP を拡張した XHP で部品を組んでいて、PHP はリクエストのたびにページを頭から組み立てるので、前に返したページのどこを直すかを考えずに済みました。 2013年5月29日に公開された React は、“re-renders the whole app on every update”(更新のたびにアプリ全体を描き直している)ように見える API にし、前回との差分だけを DOM に当てました。 この物語の軸から見ると、サーバーで毎回ページを組み立てる書きやすさを、ブラウザの中に持ち込んだ形です。2013年の公式ブログは、SEO や性能のためにサーバーで React を動かせることも、すでに書いています。
最初の HTML を、もう一度サーバーで
Section titled “最初の HTML を、もう一度サーバーで”ブラウザの端まで振れた振り子は、2つの困りごとに引き戻されます。 Airbnb は2011年、モバイル向けの Web サイトを Backbone.js の SPA で作りました。エンジニアの Spike Brehm は、クライアントでしか動かないアプリケーションはクローラーに HTML を渡せず SEO が弱いこと、利用者が数秒間、白いページか読み込み中の印を見ることを挙げています。 Twitter も2012年5月に描画をサーバーに戻し、最初のツイートが見えるまでの時間が2010年の作りの5分の1になったと書きました(Twitter 自身の計測です)。
では、PHP や CGI のころに戻ればよいのでしょうか。Brehm はもう1つ、日付の書式やフォームの検証がサーバーとブラウザで “often in different languages”(しばしば違う言語で)二重に書かれがちだという問題も挙げていました。
CSR・SSR・SSG の考え方は、ここから整理されていきます。 2011年10月17日、Nodejitsu の Charlie Robbins は、クライアントでもサーバーでも動く JavaScript を “isomorphic” と呼びました。2013年11月、Brehm はこれを、最初の HTML はサーバーで作り、その後の画面の切り替えはブラウザで行う “a hybrid of the new and old approaches”(新旧の作り方の混ぜ合わせ)として広めます。 サーバーに戻ったのは最初の HTML を作る仕事で、それを作るのはブラウザと同じ JavaScript の部品です。 前もってファイルを作る静的な生成(SSG)も、2008年の Jekyll から別の道で続いていました。 残ったのは、HTML が見えても JavaScript が動くまでは押しても応えない時間と、すべての URL を前もって作る手間です。
この「両方を取る」形を、多くの手順を踏まずに使えるようにしたのが Next.js です。
2016年10月25日に Next.js を公開した ZEIT の公式ブログは、すぐに反応する画面を作れることから、振り子が “the extreme of “single page app” / “nothing server-rendered""(「シングルページアプリ」「サーバーでは何も描かない」という極端)に一気に振れた、と書きました。
Next.js では pages に置いたファイルがそのまま URL になり、同じ React の部品がサーバーで最初の HTML を作り、ブラウザの中でページを移るときにも描き直します。README は PHP の使いやすさを手本に挙げつつ、“Unlike PHP”(PHP と違って)置くのは部品を書き出すモジュールだと書いています。
振り子はサーバーの側へ戻りましたが、PHP の位置ではなく、サーバーとブラウザが同じ部品を分け合う位置に止まりました。
ただ、2023年5月の 13.4 の発表は、getServerSideProps で描いたページはページ全体のハイドレーションが終わるまで操作できなかったと書いています。
二度描く手間を、動く部品だけに絞る
Section titled “二度描く手間を、動く部品だけに絞る”サーバーで描いた HTML は、届いた時点ではただの HTML です。
2013年1月、Rendr でモバイルサイトを作り直した Airbnb の Brehm は、HTML を捨ててブラウザで描き直す方法を選ばず、すでにある DOM に data-view を目印にしてビューを付け直しました。
のちにハイドレーションと呼ばれるこの形を、React は2017年9月の React 16 で ReactDOM.hydrate という専用の API にしています。
中身が見えるまでの時間は縮みましたが、ボタンが動くのは、ブラウザが同じ画面をもう一度組み立ててイベントをつないだあとです。2022年4月、Builder.io の Miško Hevery は “Hydration is overhead because it duplicates work.”(ハイドレーションは仕事を重複させるので上乗せだ)と評しました。
サーバーとブラウザが同じ部品を分け合う形は、同じ画面を二度処理する手間と引き換えでした。
二度手間がとくに目立つのは、動くところが少ないページです。ニュースの記事のページで動く必要があるのはカルーセルや共有のボタンくらいなのに、SPA のフレームワークはルートの部品からページ全体をハイドレーションしていました。 2020年8月11日、Jason Miller は “render HTML pages on the server, and inject placeholders or slots around highly dynamic regions”(HTML のページをサーバーで描き、動きの多い部分のまわりに場所取りの枠を入れる)という形を書きました。アイランドアーキテクチャです。名付けたのは Etsy の Katie Sylor-Miller だと、Miller 自身が記しています。 jQuery のプラグインを当てていたころと違い、島では同じ部品のコードが HTML と動きの両方を受け持ちます。その代わり、どこを島にするかと、島どうしをどうつなぐかを、作る側が前もって決めなければなりません。
この考え方をフレームワークの既定にしたのが Astro です。 2021年6月8日の発表は “There’s a simple secret to building a faster website — just ship less.”(速いサイトを作る簡単な秘訣がある。送るものを減らせばいい)と書き出し、ページをビルドのときに HTML にして JavaScript を既定ですべて取り除き、印を付けた部品にだけ JavaScript を送る形をとりました。 HTML は既定でサーバー(またはビルド)が作り、ブラウザに渡すのは動く部品だけ、という位置です。 ただし Astro はこの形を “the majority of content-based websites”(中身を読ませるサイトの大半)に最善だとしていて、在庫のようにリクエストごとに変わる中身のために、2022年の 1.0 でサーバーで描く出力を、2024年には Server Islands を実験版として足しました。動く部品の多いアプリについては、作者の Fred Schott も Next.js のほうが得意だと認めています。
5つの段で、振り子が止まった位置を並べます。
| 段 | 最初の HTML を作る場所 | 画面を動かす場所 | 次に残った困りごと |
|---|---|---|---|
| CGI・Perl・PHP | 要求のたびにサーバー | 次のページを読み直す | 操作のたびにページ全体を待つ |
| JavaScript・Ajax | サーバー | ブラウザがページの一部を | 大きくなるほど保守が難しい |
| jQuery・SPA・React | 最初の1枚だけサーバー | ブラウザが画面の切り替えまで | 検索エンジンと最初の表示 |
| CSR・SSR・SSG・Next.js | サーバーかビルド(ブラウザと同じ部品で) | ブラウザがページ全体を引き継ぐ | 見えても押せない時間と二度の処理 |
| ハイドレーション・アイランド・Astro | 既定はサーバーかビルド | 印を付けた部品だけをブラウザで | どこを島にするかと、変わり続ける中身 |
2026年10月時点の立ち位置
Section titled “2026年10月時点の立ち位置”振り子が振れても、前の位置にあったものが消えたわけではありません。章の記事が2026年10月に確かめた数字を並べます。分母はそれぞれ違います。
| 指標 | 数字 | 出典 |
|---|---|---|
| サーバーサイドの言語がわかるサイトのうち PHP を使う割合 | 69.2% | W3Techs(2026年10月28日) |
| すべての Web サイトのうち jQuery を使う割合 | 64.3% | W3Techs(2026年10月29日) |
| すべての Web サイトのうち React を使う割合 | 6.0% | W3Techs(2026年10月29日) |
| すべての Web サイトのうち Next.js を使う割合 | 3.7% | W3Techs(2026年10月) |
| この1年に React で本格的な開発をした回答者(全回答者) | 44.7% | Stack Overflow Developer Survey 2025 |
| 同じく Next.js | 20.8% | 同上 |
動いているサイトの数では、サーバーが毎回ページを作る PHP と、そのページを書き換える jQuery が大きく、開発者の調査では React と Next.js が上位にあります。 CGI そのものは、Apache HTTP Server 2.4 が mod_cgi を標準で持つ一方、Python は 3.13 で、Perl は 5.22.0 で、標準の配布物から CGI のモジュールを外しました。
SPA として作られたサイトの割合を直接示す数字は、見つかっていません。HTTP Archive の Web Almanac 2025 は、AI のクローラーは JavaScript を描画しないので、大事な情報は最初の HTML に入れておくべきだと書いています。 描く場所の選び方について、web.dev の「Rendering on the Web」は2026年1月5日の更新で、ページ全体を rehydration する作りより SSR か静的な描画を検討し、まずボトルネックを計測するよう勧めています。 ハイドレーションは React・Vue・Svelte・Angular のどれもが入口を持ち、部分ごとに行う仕組みも備えています。State of JavaScript 2025 では、メタフレームワークの分野で使う人の多さは Next.js が、満足度では Astro が首位でした。
2026年10月の時点で、振り子はどこか1点に止まったのではなく、それぞれの位置の答えが用途ごとに使われています。
- 1990年代の CGI・Perl・PHP では、要求のたびにサーバーがページ全体を作り、ブラウザは表示するだけでした。残ったのは、操作のたびにページ全体を待つことです。
- JavaScript(1995年)と Ajax(2005年に命名)でブラウザがページの一部を書き換えるようになり、jQuery・SPA・React で画面の切り替えまで受け持つようになりました。
- SPA が検索エンジンと最初の表示でつまずくと、最初の HTML はサーバーに戻りましたが、作るのはブラウザと同じ JavaScript の部品で、Next.js がそれをファイルを置くだけで使えるようにしました。
- 同じ画面を二度処理するハイドレーションの重さから、アイランドと Astro は「既定はサーバー、動く部品だけブラウザ」という位置を選びました。
- どの段も前の位置に戻ったのではなく、前の段の困りごとを引き受けて別の位置に止まり、2026年10月時点でもそれぞれの答えが用途ごとに使われています。