SPA (Single Page Application)

最初に 1 つの HTML ドキュメントをロードし、以降のページ遷移をフルリロードなしで JS が処理するアプリケーション構造。対義語は MPA (Multi-Page Application)。CSR/SSR/SSG が「初回 HTML をいつ・どこで作るか」の軸なのに対し、SPA は「2 ページ目以降をどう扱うか」の軸 — この 2 軸を分けて説明できるかがこのテーマの試金石(→ rendering-strategies)。

仕組み

遷移時にブラウザのナビゲーションを乗っ取る:

  1. リンククリックを JS がインターセプト(デフォルトのページロードを preventDefault)
  2. History API(pushState)で URL だけ書き換える
  3. 必要なデータ(JSON)やコード(動的 import)だけ fetch
  4. DOM を差し替える

HTML ドキュメントの再取得・再パース・JS 再実行が起きないので遷移が速く、アプリの状態(メモリ上のオブジェクト、再生中の動画、WebSocket 接続)が遷移をまたいで生き続ける。これが SPA の本質的な価値で、速さだけなら MPA でも追い付ける。

CSR との関係 — 同じ思想の遷移編、でも切り離せる

CSR が「初回の画面をブラウザで描く」、SPA が「遷移後もブラウザで描き続ける」— 「画面づくりをブラウザに任せる」という同じ思想の前半と後半なので、古典的にセットで使われた。ただし独立した軸なので組み替えられる:

初回 HTML \ 遷移SPA(クライアント遷移)MPA(フルリロード)
CSR古典 SPA(Create React App, Vite + React Router)(ほぼ存在しない)
SSRNext.js / Nuxt / SvelteKitRails, Django
SSGGatsbyAstro(デフォルト), Hugo

「SPA と言えば CSR」だったのは 2010 年代前半の話。現代の主流は初回だけ SSR/SSG で HTML を返し、hydration 後は SPA 遷移というハイブリッド。

歴史

年出来事
2004-05Gmail / Google Maps。XMLHttpRequest による「リロードしない Web アプリ」の衝撃(→ web2.0)
2005Jesse James Garrett が Ajax と命名
2010-13Backbone, AngularJS, Ember — SPA フレームワーク第一世代
2013-15React / Vue。仮想 DOM で SPA 開発が主流化
2016〜Next.js 等、SSR ハイブリッドへの揺り戻し
2023〜View Transitions API / Hotwire / htmx — 「MPA でもアプリ的 UX」の巻き返し

代償 — ブラウザが無料でくれていたもの

MPA ならブラウザが自動でやることを、SPA は JS で再実装する必要がある:

ブラウザの標準機能SPA での再実装
URL とページの対応クライアントルーター
スクロール位置の復元自前で保存・復元
フォーカス管理・スクリーンリーダーへの遷移通知自前(怠るとアクセシビリティが壊れる)
ページ破棄によるメモリ解放ページが長寿命化するのでリークが蓄積し得る
読み込み中の表示自前のローディング UI

加えて初回バンドルが肥大しやすい。「遷移は速いが初回が重い」は SPA の宿命で、コード分割・プリフェッチで緩和する。

向くケース

滞在時間が長く、操作が多く、状態を持ち続けたいアプリ。エディタ(Figma, Google Docs)、チャット、ダッシュボード、地図。逆に、記事を 1 ページ読んで離脱するメディアで SPA を選ぶ理由はほぼ無い。

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

関連

Graph