🚀 ニフティ’s Notion

【Webアプリ2025 #17】SPA(Single-page Application) (CSR(Client Side Rendering))

SPA(Single-page Application) (CSR(Client Side Rendering))

クライアント側のブラウザで JavaScript を実行することで、ページを表現・遷移する

  • 従来型 MPA では出来なかった、データを取得し終わった部分から順次表示していくなど、フロント側での柔軟な操作が可能
image block
https://document.microcms.io/manual/rendering-methods
microCMS がデータソースの場合
📖ページ表示方法
  1. クライアントはビルド済みの静的な HTML や JavaScript, CSS をストレージやサーバーから取得
    • HTMLの中身は基本空であり、ビルドしたJavaScriptを読み込むだけ
      • ページが1枚( index.html とか)のみ → Single-page Application
        • 逆に MVC 構成など、 web ページを遷移するごとに異なるページを HTML として受け取る方式を MPA(Multiple-page Application) と呼ぶ
  2. ページの表示・遷移などは取得した JavaScript で DOM を経由して書き換える
    • 動的なデータ(例えばユーザー情報など)は Axios , FetchAPI , Ajax など でデータだけバックエンドのサーバーから取得するよう JavaScript で記述
      • 例えば React ライブラリ(後述)で 日付取得ボタン を押したら Axios で取得し、pタグに埋め込む
💭実装イメージ
  • このHTMLに、クライアント側で動的に” root ”とかに JavaScript でHTML要素を加える
    <!DOCTYPE html>
    <html lang="ja">
    
    <head>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="theme-color" content="#000000" />
      <meta name="description" content="Web site created using create-react-app" />
      <link rel="manifest" href="/manifest.json" />
      <title>SPAテスト</title>
    <script defer src="/static/js/bundle.js"></script></head>
    
    <body>
      <noscript>You need to enable JavaScript to run this app.</noscript>
      <div id="root"></div>
    </body>
    
    </html>
    要素の追加

    例えば、 Web API である Node インターフェースが提供している appendChild で追加

      <script>
        const rootDiv = document.getElementById('root');
    
        const hello = document.createElement('div');
        rootDiv.appendChild(hello);
    
        const title = document.createElement('h1');
        title.textContent = '`appendChild` Example in Vanilla JavaScript';
        hello.appendChild(title);
      </script>
    https://developer.mozilla.org/ja/docs/Web/API/Node/appendChild#本文に段落を追加

    例えば、Web API である Fetch API でデータ取得後に要素を表示

    <script>
      async function handleFetchClick() {
        fetchDataContainer.innerHTML =
          '<p class="text-green-800 text-lg">Loading data...</p>'; // Loading message
    
        try {
          // Fetch data from JSONPlaceholder
          const response = await fetch(
            "https://jsonplaceholder.typicode.com/posts/1"
          );
          if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
          }
          const data = await response.json();
    
          // Clear loading message and display data
          fetchDataContainer.innerHTML = ""; // Clear previous content
    
          const dataTitle = document.createElement("h3");
          dataTitle.className = "text-xl font-semibold text-green-900 mb-2";
          dataTitle.textContent = data.title;
          fetchDataContainer.appendChild(dataTitle);
    
          const dataBody = document.createElement("p");
          dataBody.className = "text-green-700";
          dataBody.textContent = data.body;
          fetchDataContainer.appendChild(dataBody);
        } catch (error) {
          console.error("Error fetching data:", error);
          fetchDataContainer.innerHTML = `<p class="text-red-600 text-lg">Error: ${error.message}. Could not fetch data.</p>`;
        }
      }
    
      // Add event listener for fetch button
      if (fetchButton) {
        fetchButton.addEventListener("click", handleFetchClick);
      }
    </script>
    
  • svelte : SSRをオフにするとSPA
  • https://nextjs.org/docs/app/building-your-application/rendering/client-components#using-client-components-in-nextjs
メリット
  • サーバーからページをすべて読み込む必要が無いので、初回の読み込み以降は高速
  • 静的なアセット( HTML , CSS , JavaScript )が置ければ機能する
  • サーバーサイドの言語が不要になり、すべて JavaScript で記述できるため開発効率が上がる
デメリット
  • SEO で不利になりやすい
    • クローラーによっては、 JavaScript をサポートしていなかったり、サポートしていても時間が掛かる
      • 例: Google, Bing のクローラー
  • 最初は空の HTML で、ファイルのダウンロードからレンダリングまでが重い = 1ページ目の表示が遅い
  • JavaScript 前提なので、 JavaScript がオフのブラウザでは真っ白に見える
    • noscript タグで対応
✨有名なCSR向けフレームワーク
  • React
  • Vue.js
  • Angular
SPA(Single-Page Application)

CSR では、 MPA とは異なり、ページ(HTML)は1つで、JavaScriptで表示内容を制御する。

これを MPA と比較して SPA(Single-Page Application) と呼ぶ