SPA(Single Page Application/シングルページアプリケーション)は、最初に1枚のHTMLだけを読み込み、以降の画面切り替えをJavaScriptで書き換えて行うWebアプリの作り方です。ブラウザで動かす以上、開発言語の中心はJavaScriptとTypeScriptで、Dart・C#・RustもWebAssemblyやJavaScriptを介してブラウザで動かせます。この記事では、仕組みを30行ほどのコードで示したうえで、言語とフレームワーク(React 19.3・Vue 3.5・Angular 22など2026年10月時点の現行版)の選び方、SEOと初期表示の弱点、MPA・SSRとの使い分けまでを整理します。
なお、アパレル業界の「SPA(製造小売業)」は綴りが同じだけの別の言葉です。この記事はWeb開発のSPAだけを扱います。
まとめ:SPAの仕組み・言語・選び方の要点
- SPAは1枚のHTMLを読み込んだあと、URLの変更と画面の描き替えをブラウザ側のJavaScriptで行います。2画面目以降の遷移は速い一方、最初の表示はJavaScriptを読み終えるまで待たされます。
- 開発言語はJavaScriptかTypeScriptが前提です。ブラウザが直接実行できるのはJavaScriptとWebAssemblyだけで、Dart(Flutter)とRust(Leptos)はどちらかへ変換して動かし、C#(Blazor)はWebAssembly上の.NETランタイムで実行します。サーバー側のAPIは言語を問いません。
- フレームワークは、画面数が多く規約で統一したいならAngular、既存ページへ部分的に入れたいならVue、周辺ライブラリを自分で選びたいならReactです。新規のReactで
create-react-appは2025年2月に非推奨になり、Viteかフレームワークで始めます。 - 検索から人を集めるページはSPAに向きません。ログイン後の管理画面・ダッシュボード・エディタはSPA、記事やLP・商品詳細はSSRかSSGで作り、同じアプリの中で画面ごとに方式を分けます(Next.jsも、SPAや静的サイトで始めて必要に応じてサーバー機能を足す構成を案内しています)。
- Googleは、SPAのルーティングに
#付きURLを使わずHistory APIを使うこと、存在しないURLでsoft 404を出さないことを公式に求めています。
SPAの仕組み:1枚のHTMLをJavaScriptで書き換える方式
MDNの用語集は、SPAを「単一のWeb文書だけを読み込み、別の内容を表示するときはFetchなどのJavaScript APIでその文書の本文を書き換えるWebアプリの実装」と定義しています(MDN Glossary: SPA)。同じ項目は、代わりにSEO・状態の維持・ナビゲーションの実装・性能の計測に手間がかかるとも注記しています。ブラウザが本来やってくれる仕事をアプリ側で引き受ける方式です。
MPA(従来型)との違いを5項目で比較
リンクを押すたびにサーバーから新しいHTMLを受け取る従来型のWebサイトをMPA(Multi Page Application)と呼びます。違いは次のとおりです。
| 項目 | SPA | MPA |
|---|---|---|
| サーバーが返すもの | 初回はHTML1枚+JS、以降はJSONなどのデータ | 画面ごとのHTML |
| 最初の表示 | JSの読み込み・実行を待つ | HTMLが届けばすぐ描画 |
| 2画面目以降の遷移 | 差分だけ描き替えるので速い | 毎回ページ全体を読み直す |
| URLと履歴 | History APIで自前管理 | ブラウザが自動で管理 |
| 検索エンジン対応 | 設計上の配慮が必要 | 標準で対応しやすい |
サーバーでHTMLを組み立てるSSR、ビルド時にHTMLを作るSSGとの違いは、描画の場所とタイミングの問題です。方式ごとの比較はCSRとSSRの違いと使い分け|レンダリング方式を比較して実装で選ぶで詳しく扱っています。
History APIで画面を切り替える最小コード
フレームワークを使わずに書くと、SPAの中身は「リンクのクリックを横取りする」「URLを書き換える」「表示を差し替える」「戻るボタンに追従する」の4つです。history.pushState() の第3引数に渡したURLは履歴に積まれ、アドレスバーにも表示されます(MDN: Working with the History API)。
<nav>
<a href="/">ホーム</a>
<a href="/products">商品一覧</a>
</nav>
<main id="view"></main>
<script>
const routes = {
"/": () => "<h1>ホーム</h1>",
"/products": () => "<h1>商品一覧</h1>",
};
function render(path) {
const view = routes[path];
document.getElementById("view").innerHTML = view ? view() : "<h1>見つかりません</h1>";
}
document.addEventListener("click", (e) => {
const a = e.target.closest("a");
if (!a || a.origin !== location.origin) return;
if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
e.preventDefault();
history.pushState({}, "", a.pathname);
render(a.pathname);
});
window.addEventListener("popstate", () => render(location.pathname));
render(location.pathname);
</script>
このコードは開発サーバーでは動きますが、本番でつまずく点が2つあります。1つ目は、/products を直接開いたりリロードしたりすると、サーバーにはそのパスのファイルが無いため404になることです。どのパスにも同じ index.html を返す設定(履歴フォールバック)がサーバー側に要ります。Viteの開発サーバーは appType の既定値が 'spa' なのでこの処理を自動で行い、vite preview でもフォールバックが効くため、本番サーバーの設定漏れは公開後まで気づきにくくなります。2つ目は「見つかりません」の画面がHTTPステータス200で返る点で、これは後述のsoft 404にあたります。
History APIの後継にあたるNavigation APIは、MDNで2026年1月にBaseline(主要ブラウザーの最新版で利用可)に到達しました(MDN: Navigation API)。画面切り替えにアニメーションを付ける同一ドキュメントのView Transitions APIも2025年10月にBaselineへ入っています。Navigation APIでのルーティング実装は業務システムのSPA化とは?判断基準・公開事例・移行手順を実装目線で解説【2026年版】、遷移アニメーションはView Transitions APIの対応ブラウザと実装手順|クロスドキュメント遷移までで扱っています。
SPAの開発言語:JavaScriptとTypeScriptが前提になる理由
SPAの画面側は、ブラウザの中で動くコードです。ブラウザが直接実行できる言語はJavaScriptと、バイナリ形式のWebAssemblyの2つしかありません。どの言語で書いても、最後はこのどちらかの形でブラウザへ届きます。
TypeScriptが実務の標準になっている理由
TypeScriptはJavaScriptに型を足した言語で、ビルド時にJavaScriptへ変換されます。SPAはAPIから受け取ったJSONを画面の状態に詰め替える処理が大半を占めるため、APIのレスポンスの形を型で書いておくと、項目名の打ち間違いや型の取り違えをブラウザで動かす前に見つけられます。Angularは最初からTypeScriptで書く前提で、ViteのReact・Vue用テンプレートにも react-ts・vue-ts が用意されています。npmの最新版は2026年10月11日時点で7.0.2です。7系の変更点はTypeScript 7とは?Go製ネイティブコンパイラtsgoで最大10倍高速化|RC公開と移行の要点【2026年最新】を参照してください。
JavaScript以外で書く選択肢:Dart・C#・Rust
JavaScriptを書かずにSPAを作る手段も、各言語の公式が用意しています。
| 言語 | 手段 | ブラウザで動く形 | 向く場面 |
|---|---|---|---|
| Dart | Flutter Web | JavaScript/WebAssembly | 描画の多いアプリ、モバイル版との共通化 |
| C# | Blazor WebAssembly | WebAssembly上の.NETランタイム | .NETの資産がある業務システム |
| Rust | Leptos 0.8・Yew 0.23 | WebAssembly | 計算量の多い画面 |
Flutterの公式ドキュメントは、Flutter Webが最も役立つ場面の筆頭に「グラフィックや操作の多い、単独で動くSPA」を挙げる一方、ブログ記事のような文章中心の静的なページには向かないと明記しています(Flutter: Web support)。Blazor WebAssemblyは.NET 10の公式ドキュメントでも現行のホスティングモデルで、RazorコンポーネントをWebAssemblyベースの.NETランタイムでブラウザ側実行します。C#がWebAssemblyへ直接変換されるのはAOTコンパイルを有効にしたときだけで、既定ではWebAssembly上のILインタープリターが実行します(Microsoft Learn: Blazor WebAssembly build tools and AOT)。採用判断はBlazorの将来性は?2026年の採用判断と.NET 10時代のWeb開発を解説、RustからWebAssemblyを作る手順はRustでWebAssemblyを実装する手順|wasm-packでのWASM化と軽量化・配置先の選び方【2026年版】にまとめています。
どれもブラウザAPIや周辺ライブラリの部分でJavaScriptの知識は要ります。社内にその言語の開発者がいて、既存コードを流用できるときに選ぶ手段です。
サーバー側(API)の言語:Java・Go・PHP・Pythonなど自由に選択
SPAでは画面とデータ取得が分かれ、ブラウザはサーバーとJSONでやり取りするだけになります。そのため、API側はJava・Go・PHP・Python・C#など、画面側と無関係に選べます。画面とAPIの役割分担はフロントエンドとバックエンドの違いとは?役割・言語・連携と開発発注時の体制設計を解説で詳しく説明しています。
SPAのフレームワーク:現行版と選び方(2026年10月時点)
ルーティング・状態の管理・差分更新を自前で書かずに済むよう、実務ではフレームワークを使います。以下はnpmレジストリで2026年10月11日に確認した最新版です。
| 分類 | パッケージ | 最新版 | 補足 |
|---|---|---|---|
| UI | react | 19.3.0 | 2026-09-09公開 |
| UI | vue | 3.5.43 | 3.6はRC段階 |
| UI | @angular/core | 22.2.2 | v22は2028年6月までサポート |
| UI | svelte | 5.57.2 | コンパイル型 |
| メタFW | next | 16.4.0 | React系 |
| メタFW | nuxt | 4.6.1 | Vue系 |
| ルーター | react-router | 8.4.0 | SPAモードあり |
| ビルド | vite | 8.3.4 | 各UIのテンプレートを提供 |
React・Vue・Angularの選び分け
機能の優劣より、チームの体制と既存資産で決まります。
- Angular:ルーター・フォーム・HTTP通信・テストが公式に揃い、書き方が規約で揃います。画面数が多く、開発者の入れ替わりがある業務アプリ向きです。公式のリリース方針では各メジャー版を通常24か月(通常サポート12か月+LTS 12か月)支え、v22は2028年6月にLTSが終わります。詳細はAngular 22.1とは?v22系の変更点とリリース体制の転換を実装目線で解説を参照してください。
- Vue:HTMLテンプレートに近い書き方で、ビルド環境を用意せずに既存のサーバー描画ページの一部へ組み込むこともできます(Vue: Ways of Using Vue)。全面作り直しではなく、段階的に画面をSPA化したいときに選びやすいフレームワークです。
- React:Reactが担うのは画面の部品だけで、ルーターや状態管理は自分で選びます。自由度が高い分、構成を決める人がいないと案件ごとに構成がばらつきます。両者の比較はReactとVue3の違いを比較|どっちを選ぶべきか初心者向けに解説にまとめています。
配信するJavaScriptを小さく抑えたい場合は、コンポーネントをビルド時にコンパイルするSvelteも候補になります。
Reactの始め方:create-react-app非推奨後のVite
Reactチームは2025年2月14日に、新規アプリ向けの create-react-app を非推奨にしました。保守担当者がいないことを理由に、フレームワークか、Vite・Parcel・Rsbuildなどのビルドツールへ移るよう案内しています(React Blog: Sunsetting Create React App)。ブラウザだけで完結するSPAをReactで始めるなら、Viteで次のように作ります。
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
Vite 8での環境構築と、既存の create-react-app からの移行手順はViteとは?Reactの環境構築手順とVite 8の変更点・create-react-appからの移行で解説しています。
SPAの弱点と対策:初期表示とSEO
問題になりやすいのは、最初の画面が出るまでの時間と検索エンジンへの見え方です。
初期表示の遅さ:JavaScriptの読み込み待ちとLCPの目標値
Next.jsのドキュメントは、HTML1枚ですべてをブラウザ側で描く「厳密なSPA」について、操作できるようになる前に大量のJavaScriptの読み込みが必要になりがちで、ブラウザ側のデータ取得が数珠つなぎになる問題も管理しにくいと指摘しています(Next.js: How to build single-page applications)。対策は2つです。
- 画面ごとにJavaScriptを分割し、開いた画面の分だけ読み込む(動的
import())。主要なフレームワークのルーターは、ルート単位の分割に対応しています。 - 最初の1画面だけはサーバーかビルド時にHTMLを作っておき、遷移はSPAとして動かす。
目標値は、Googleの指標であるLCP(最大の要素が表示されるまでの時間)で決めます。web.devは、ページ読み込みの75パーセンタイルで2.5秒以下を「良好」の基準にしています(web.dev: Largest Contentful Paint)。
SEO:Googleが公式に求める3つの対応
GooglebotはJavaScriptを実行して内容を読むので、SPAでも検索には出ます。ただしGoogle Search CentralのJavaScript SEOの基本と動的レンダリングのガイドは、SPAに対して次の対応を求めています。
- URLの切り替えはHistory APIで行う:
href="#/products"のようなフラグメントで別の内容を読み込むと、GooglebotがURLを確実に解決できません。リンクはhref付きの<a>要素で書きます。 - soft 404を出さない:存在しないURLで「見つかりません」画面をステータス200で返すと、soft 404として扱われます。サーバーが404を返すURLへJavaScriptでリダイレクトするか、その画面に
noindexのrobotsメタタグを付けます。先の最小コードの「見つかりません」画面は、この対応が要る典型例です。 - 動的レンダリングに頼らない:検索エンジンのボットにだけサーバー描画版を返す動的レンダリングを、Googleは「回避策であり推奨される解決策ではない」と位置付けています(Dynamic Rendering as a workaround)。検索流入が要るページは、最初からSSRかSSGで作ります。
Reactでの具体的な実装手順はReact SEO対策とは?SSR・SSG・プリレンダリングの選び方と実装手順で扱っています。
SPA・MPA・SSR・SSGの使い分け
サイト全体ではなく、画面ごとに方式を選びます。目安は次のとおりです。
| 作るもの | 向く方式 | 決め手 |
|---|---|---|
| 管理画面・ダッシュボード | SPA | ログイン後で検索流入が不要 |
| 地図・エディタ・チャット | SPA | 状態を保ったまま操作が続く |
| ECの商品一覧・詳細 | SSR/SSG+部分的なJS | 検索流入と最初の表示が売上に直結 |
| ブログ・メディア・LP | SSG/MPA | 1回読んで離脱する文章中心のページ |
描画方式そのものの仕組みはレンダリングとは?ブラウザ描画の仕組みとCSR/SSR/SSGの違い・選定基準を解説で、SPAとMPAの中間にあたる構成はPESPAとは?SPA・MPAとの違いとRemix後継(React Router v8)での実装を解説【2026年8月版】で解説しています。
SPAを採用すべきでない場面
次のどれかに当てはまるなら、SPAは選びません。
- 流入の大半が検索で、1ページ読んで帰る:記事・LP・会社案内がこれにあたります。SPAの利点である「2画面目以降の速さ」が使われないまま、最初の表示の遅さだけを抱えます。言語の章で触れたFlutter公式の「文章中心の静的なページには向かない」という注意書きも、同じ線引きです。
- SSRやsoft 404対策を設計できる人がチームにいない:前章の対応を後から足すのは、最初から入れるより手間がかかります。
- 利用者の端末が古く、通信が細い:店舗の共用端末や海外拠点の回線など、JavaScriptの読み込みと実行が重い環境では、MPAのほうが速く感じられます。
SPAから始めてサーバー機能を足す構成:Next.jsの静的エクスポート
最初はSPAで小さく始め、検索流入が要る画面が出てきた時点でSSRへ広げる進め方もできます。Next.jsは next.config.ts に output: 'export' を書くと、ルートごとのHTMLを含む静的ファイルを out フォルダに出力し、HTMLを配信できる任意のWebサーバーに置けます(Next.js: Static Exports)。この形ではリクエストごとのSSR、Server Actions、リクエスト情報を読むRoute Handlerなどは使えません(Server Componentsはビルド時に実行されます)。後から設定を外せば、これらのサーバー機能を段階的に足せます。
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
output: 'export',
}
export default nextConfig
React Routerにも、サーバー描画を切ってSPAとして出力するモードがあります。設定と制約はRemix SPAモードとは?ssr:falseの設定と制約、React Router移行の判断を、Next.js自体の始め方はNext.jsとは?16系App Routerで最小アプリを動かす手順と採用判断を参照してください。
SPA開発を開発会社に依頼するときの確認項目
発注前に、次の5点が提案書か見積もりに入っているかを確認してください。見積もりで抜けた作業ほど公開直前に表面化します。
- サーバーの履歴フォールバック:どのURLを直接開いてもアプリが起動する設定(最小コードの章で触れた1つ目の落とし穴)を、インフラ作業として見積もっているか。
- 存在しないURLの扱い:soft 404対策を誰が実装するか。
- 最初の表示の目標値:「高速」ではなく、LCP 2.5秒以下のように数値で合意しているか。
- フレームワークの更新費用:保守契約にメジャー版の更新作業を含めるか。Angular 20のLTSは2026年11月28日に終わるため、v20で納品された案件は2026年内に更新が必要になります。
- 検索流入が要る画面の扱い:その画面をSPAから外してSSRかSSGにする判断を、設計段階で済ませているか。
Webに加えてiOS・Androidのアプリも同じコードで出したい場合は、Flutter WebやReact Nativeを前提に体制を組むと、画面の部品と業務ロジックを共有できます。弊社ではFlutter / React Native開発として、この構成での開発を支援しています。業務システムを段階的にSPAへ移すときに発注側が決めておく項目は、業務システムのSPA化とは?判断基準・公開事例・移行手順を実装目線で解説【2026年版】で整理しています。
よくある質問
SPAとは何の略ですか?製造小売業のSPAとは違いますか?
Web開発のSPAはSingle Page Application(シングルページアプリケーション)の略です。アパレルなどの「SPA(製造小売業)」は、企画から製造・販売までを自社で一貫して行うビジネスモデルを指す別の言葉で、技術とは関係ありません。
SPAのメリットとデメリットは何ですか?
メリットは、2画面目以降の遷移が速く、入力中の状態を保ったまま操作を続けられることです。デメリットは、最初の表示がJavaScriptの読み込みを待つ分だけ遅くなること、検索エンジン向けにHistory APIやsoft 404対策などの配慮が要ること、URLや履歴の管理をアプリ側で引き受けることです。
SPAとMPAの違いは何ですか?
MPAは画面ごとにサーバーから新しいHTMLを受け取り、SPAは最初の1枚のHTMLをJavaScriptで書き換え続けます。最初の1画面はMPAが速く、2画面目以降はSPAが速くなります。
SPAの開発に必要な言語は何ですか?
画面側はJavaScriptかTypeScriptです。DartのFlutter Web、C#のBlazor WebAssembly、RustのLeptosのように他の言語で書く手段もありますが、ブラウザではいずれもJavaScriptかWebAssemblyの形で動きます(Blazorは既定でWebAssembly上の.NETランタイムが実行)。サーバー側のAPIは言語を問いません。
SPAはSEOに不利ですか?
作り方次第です。GooglebotはJavaScriptを実行して内容を読みますが、# 付きURLでの画面切り替え、存在しないURLへのステータス200の応答(soft 404)は避ける必要があります。検索流入が主目的のページは、SPAではなくSSRかSSGで作るのが確実です。