SPA(Single Page Application)について勉強したことをまとめました

# この記事のきっかけ

最近、Vueを触る機会が増えてきたのですが、どうやって表示されているのか気になったので勉強したことをまとめてみました！SPAと呼ばれるアプリケーションは、どのように表示されているのでしょうか。

# そもそもSPAって何？

SPAは、Single-Page Applicationの略で、和訳は「単一ページのアプリケーション」といったところでしょうか。「単一のページってなんだ？」と思うかもしれませんが、これは単純に「HTMLファイルが一つしかない」ということを示しています。

では、HTMLファイルが複数個ある構成のアプリケーションはなんと呼ぶでしょうか。答えはシンプルで、単一を複数に変えるだけです。Multi-Page Applicationと呼ばれています。

HTMLファイルが一つの場合は、SPA。複数ある場合は、Multi-Page Application（MPA）と分類しているということですね！

## どうやって表示しているの？
SPAが「単一のHTMLファイルで表示するアプリケーション」ということは理解していただけたと思います。

では、一体どのようにして複雑なアプリケーションを、単一のHTMLファイルで表示しているのでしょうか。

:::note
この記事では、主にJavaScriptフレームワーク(ライブラリー)を使用した表示方法を紹介します。
:::

### フレームワーク

Angular, React, Vue, Svelteといったフレームワークは、SPAの原則を使用しています。つまり、単一のHTMLファイルに、JavaScriptを用いて内容を書き換え、表示を行う役割を担っています。

![analogy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3790952/cbdfc5d2-6ef7-9b01-d4db-5b6fb68edd2c.png)

SPAでは何もないHTMLファイルに、JSを用いてUIを表示しています。MPAでは完成した絵を見ているのに対して、SPAはその場で絵を描き上げられるのを見ている、という気持ちになりますね。

なんとなく理解できてきましたが、「どこに何を表示する」という処理が、どのように制御されているのか気になりますね。

### ルートエレメント

ルートエレメントは、HTMLファイル内に定義されている要素のことで、アプリケーションの全てのコンポーネントが挿入される箇所です。先ほどの絵の例えだと、絵を描くキャンバスに該当しますね。

各種フレームワークは、このルートエレメントにマウントし、ユーザーの操作や状態の変化に応じて表示する内容を変更しています。

なお、VueやReactは、`<div id="app"></div>`といった要素がルートエレメントとして指定されることが多いです。

つまり、ルートエレメントにマウントし、内部的に「どこになにを表示するか」を制御しているのですね。

### ルーター

では、ページ遷移はどのように行われているのでしょうか。

SPAは、ページ遷移時にリフレッシュを行わず、ネイティブアプリケーションのようにサクサク動きます。単一のHTMLファイルに、JS制御でUIを表示しているのに、どのようにページ遷移をしているのか気になりますよね。

ここで登場するのがルーターです。VueやReactといったフレームワークでは、実際にページ遷移をしているのではなく、ルーターを使って**ページ遷移しているように見せかけて**います。

SPAはJS制御で表示する内容を変えているので、表示内容が変えられそうなのは理解できますね。

ですが、URLの処理や、ブラウザの「戻る」ボタンを押下した際の処理などは、どのように行われているのか疑問が残りますね。

### Navigation API

これらの問題を解決するのが、Navigation APIです。

ルーターはこのAPIを使い、ブラウザの履歴を更新します。これにより、ユーザーがブラウザの戻るボタンを押下した際に、適切なコンテンツを表示することができます。

また、ルーター側でどのURLが、どのコンポーネントやビューに該当するのかを記録しておき、そのマッピングに該当するUIを表示しています。

:::note warn
Navigation APIは、従来のHisotry APIの短所を解決し、SPA特化として作成された後継APIです。
まだ一般的には利用されていませんが、今後使用が広がる期待と、説明の抽象化を行うために使用しています。
:::

## 利点と課題

SPAがどういったものか、なんとなく理解していただけたと思います。

ですが、なぜここまでして単一のHTMLファイルを使いたいのか、気になりますね。

### 利点

主に、UXの向上という観点から選ばれることが多いよいうに感じます。

リッチなユーザーインタラクションが作成できるという点、ページ遷移時にもリフレッシュがなくサクサク動くという点。SPAがもたらすこれらの利点は、ユーザーのネイティブアプリケーション慣れから来る期待値に応えるべく存在している、と言っても過言ではありません。

そんなSPAですが、いいことづくしというわけではありません。

### 課題

SPAは単一のHTMLファイルにマウントするという特性上、大きく分けて二つの課題が存在します。

一つは、マウントされないと真っ白なHTMLが表示されるという点です。ルートエレメントに対してマウントしUIを表示しているので、マウントされないと何もないHTMLファイルが表示されています。

ユーザーがJavaScriptを無効にしていたり、電波環境の悪い状況下では、真っ白な画面が表示されてしまいます。

もう一つの課題は、JavaScriptの読み込みに時間がかかるという点です。ルートエレメントに対しアプリケーションコード（JS）をマウントするため、大きなJSファイルを読み込む必要があります。

これらの課題は、SEOへの悪影響（SEOメトリックの悪化、そもそもクローラーが読み込まない）や、UXへの悪影響をもたらします。

実際には、こうした課題は解消されつつあります。SPAをより強化させる、その他の表示方法を紹介して終わりたいと思います。

## その他のレンダリングパラダイム

### SSR (Server-Side Rendering)

SSRは、サーバー側でHTMLを生成し、クライアントに送信する方法です。これにより、初期表示時に完全なHTMLが送信されるため、ページのロード時間が短縮されるという利点があります。JavaScriptが有効でない環境でも、最初のページ表示が可能なため、UXやSEOの向上が期待できます。

### SSG (Static-Side Generation)

SSGは、ビルド時にすべてのページを事前に生成する方法です。完全に静的なファイルとしてホスティングされるため、非常に高速なページ読み込みが可能になり、サーバー負荷も軽減されます。

この他にも、使用するフレームワークによって、様々な表示方法があるので試してみてください。

それでは、Happy Coding~

## 参考文献

https://developer.mozilla.org/en-US/docs/Glossary/SPA

https://web.dev/learn/pwa/architecture

https://en.wikipedia.org/wiki/Single-page_application

https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API

https://developer.chrome.com/docs/web-platform/navigation-api