SPAとMPAの違い

本投稿は TECOTEC Advent Calendar 2025 の10日目の記事です。

​こんにちは。システム開発第二事業部の杉原です。 普段はSPA(シングルページアプリケーション)のバックエンド開発を担当しています。

皆さんは、SPA という言葉をご存じでしょうか? 単一のページでコンテンツの切り替えのみを行うWebアプリケーションの実装手法、という説明を聞いたことがある方も多いかと思います。しかし「概念は知っているけど、実際に何をしているのか分からない」という方も少なくないでしょう。

今回は、SPAとMPAそれぞれの構成で作成したTodoアプリを比較しながら、SPAの特徴を整理したいと思います。

当記事の目標

今回の記事では

「概念は知っているけど、実際に何をしているのか分からない」 という方向けに、

  • SPAとMPAの描画処理は具体的にどう違うのか
  • SPAはMPAと比べてどこが優れているのか

上記二点を理解していただけることを目標とします!

比較に用いるアプリについて

今回は、

  • SPA

    • FE: Vue 3 + TypeScript
    • BE: Laravel
  • MPA

    • FE: Blade
    • BE: Laravel

という構成で、Todoアプリを作成、比較しました

実際の画面

それぞれの実装方法で作成したWebアプリです

image.png


image.png
タイトル以外同じ構成に見えますが…

スクリーンショット 2025-12-07
182806.png

スクリーンショット 2025-12-07
182742.png
読み込んでいるHTMLの構造は大きく異なります。

SPAとMPAの違い

ブラウザでは、

HTMLをDOM*1に変換 → DOMをもとに画面に表示

という流れで画面を作っています

MPAの場合

  1. サーバーがHTMLを生成して返す

  2. 画面更新のたびにHTML全体を取得

  3. ブラウザがDOMを再構築 → 画面全体の更新が必要になり、遷移や描画が重くなる

SPAの場合

  1. 最初の1回だけHTML(index.html)を読み込む

  2. 画面遷移の代わりにJS(Vue)がDOMを操作

  3. データはAPI(JSON)で取得 → HTML全体の更新は発生せず、画面更新が軽くなる

実例:タスク追加の挙動

Todoアプリのタスクを追加することで、画面の更新のされ方を見てみます

MPA

タスクを追加すると…

スクリーンショット 2025-12-08
031640.png


image.png

①POST http://127.0.0.1:8000/tasks

②GET http://127.0.0.1:8000/tasks

2つのメソッドが実行されました! ①でデータベースが更新され、 ②でHTMLが返ってきます(②のレスポンス一部抜粋)

<ul>
    <li>
        <form action="http://127.0.0.1:8000/tasks/3" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="PATCH">
<input type="checkbox" onchange="this.form.submit()" >
        </form>

        タスク1

        <form action="http://127.0.0.1:8000/tasks/3" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="DELETE">
 <button>削除</button>
        </form>
    </li>
    <li>
        <form action="http://127.0.0.1:8000/tasks/4" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="PATCH">
<input type="checkbox" onchange="this.form.submit()" >
        </form>

        タスク2

        <form action="http://127.0.0.1:8000/tasks/4" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="DELETE">
 <button>削除</button>
        </form>
    </li>
    <li>
        <form action="http://127.0.0.1:8000/tasks/5" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="PATCH">
<input type="checkbox" onchange="this.form.submit()" >
        </form>

        追加タスク

        <form action="http://127.0.0.1:8000/tasks/5" method="POST"
style="display:inline">
            <input type="hidden" name="_token"
value="V2QYf2RF4XN7uUyYRRodPGlCxAKo68YTKHpsyHaS" autocomplete="off">
         <input type="hidden" name="_method" value="DELETE">
 <button>削除</button>
        </form>
    </li>
</ul>

SPA

タスクを追加すると…

スクリーンショット 2025-12-08
032721.png


スクリーンショット 2025-12-08
032735.png

①POST http://localhost:5173/api/tasks

のみが実行されました!

レスポンスを確認すると

{
created_at: "2025-12-07T18:27:23.000000Z",
id: 20,
title: "追加タスク",
updated_at: "2025-12-07T18:27:23.000000Z",
}

追加したデータのみがJSON形式で返ってきます!

このデータをもとに、DOMの更新のみを行っているため、

image.png

実際のHTMLには変化がありません!

画面描画までの流れのまとめ

MPAの場合

  1. リクエストを Laravel が受け取る
  2. routes/web.php が リクエストに対応するコントローラーを探す
  3. コントローラーのメソッドが実行される
  4. コントローラーが実行結果をBladeに渡す
  5. BladeがHTMLをレンダリング
  6. HTMLをブラウザに渡す

SPAの場合

  1. リクエストを Vue が受け取る
  2. Vite dev server が index.html を返す
  3. index.html が Vue アプリ本体を読み込む(main.ts)
  4. Vue Router が現在の URL に応じて表示するコンポーネントを切り替える
  5. 表示に必要なデータは、 Laravel にリクエストする(/api/...)
  6. LaravelがAPIレスポンス( JSON )を返す
  7. Vue(JS) が JSON を画面に反映

結論

  • MPA … サーバー側がHTMLを作成 → ブラウザに返す

  • SPA … 初回に読み込んだHTMLをもとに、ブラウザ側のJSでDOMを操作

そのため、SPAでは画面更新が高速で軽量になります!

テコテックの採用活動について

テコテックでは新卒採用、中途採用共に積極的に募集をしています。
採用サイトにて会社の雰囲気や福利厚生、募集内容をご確認いただけます。
ご興味を持っていただけましたら是非ご覧ください。 tecotec.co.jp

*1:JavaScriptがHTMLを操作するために構築するオブジェクトのこと