SPA(Single Page Application) を採用するメリット再考(2020年）

# 1. 2010～2020年にかけて、WebシステムはSPAで作るのが主流

　近年、WebシステムはJavascript(Typescript）を用いたSPA(Single Page Application）を作ることが主流になっている。
　とはいえ、本当に、一つのHTMLファイルだけで、全画面をJavascriptで描画するSPAがどれだけあるかは分からないが、少なくとも、SPAで"作ろう"とはしている。
　（2010年はSPAの黎明期で、Backbone.jsやknockout.jsが生まれた年）

# (1) SPAの構成要素

　**"Single Page"**に着眼するならば、SPAは、以下を特徴とする。
　ページの基本となるHTMLファイルを1回のリクエストで取得し、その後の画面描画に関しては、大半を初回に取得したブラウザ上のリソースで行う。そして、適宜、必要なデータのみAPIへの問合せで取得する。

　そして、SPAを特徴づけるのは、描画のパーツを作成するComponent、そして、画面遷移を実現するRouterの存在であると思う。そして、状態の管理をするState Manager（VuexやRedux）によりアクションと描画が連結される。

### a. Component：視覚要素の部品

　ReactやVueを使って作られる、視覚要素の部品、すなわち、Componentは、SPAにあっては画面の描画を行う基本となる。特に、データバインディングによりHTMLのタグとJavascriptのデータを双方向で対応付け、動的に互いの状態変化を伝達する仕組みをもつのが特徴的だと思う。
　そして、これらの要素を細かく管理し、適宜、必要な部品を描画することでページ全体をサーバから取得する必要がなくなる。
　SPAの心臓部分といっても過言ではないと思う。
　
### b. Router：画面遷移の管理

　Routerは、画面というグループでComponentの配置換えを指示するコントローラー。そして、React RouterやVue Routerのように、URLの指定によって、画面を描画することで、既存のWebページと同じ画面遷移方法やUXを提供している。

### c. State Manager（状態管理）

 最小構成を考えた時、これがないとSPAが本当に成立しないかは別にして、実際にアプリケーションを作る上では、画面上のアクションやイベントをうけて、値や状態の変化をComponentの描画につなげていくときに、VuexやReduxのような状態管理モジュールが利用される。
　Componentは、タグとJavascriptの値の双方向バインディングを特徴とするが、データの流れを規制することで、意図しないデータ変更を防ぎ、バグの防止、バグの早期発見に役立つ。
　大量のComponentや状態を扱ううえでは、必要な構成要素であると思う。

# 2. jQuery不要論の背景

　SPAの登場と共に、jQuery不要論も散見されるようになった。
　ただ、それはSPAを作ろうとする上での話で、SPAをしないのであれば、jQueryは依然として便利なライブラリである。
　jQueryの特徴としては以下が挙げられる。

## (1) jQueryの特徴、メリット

- Javascriptのシンタックスシュガー、すなわち、既存の構文などを別の構文や記法で記述できるようにしたもの。
- ツールプリセットであり、事前に様々な処理を関数として定義し手軽に利用できるようにしたもの。
- 既存のHTML構造を外部から、HTMLを壊すことなく操作したり、イベントを設定できる。

## (2) jQueryはSPA専用のライブラリではない

　jQueryはSPAを作るために作られたものではないので、SPAを作ろうとすると不要と言われるのは当然である。
　もちろん、jQueryは先に上げたように、Javascriptを便利に扱うためのAltJS的な存在でもあるので、それをつかってSPAを作れなくもない。

　ただ、それよりはすでにSPAの構成要素がすでに作られている、ReactやVueをつかって、Componentをつくったした方がSPAを作るには便利なのは確かである。

　jQueryは、先に上げた、SPAの構成要素(Component、Router、State Manager）を標準でもっているわけでもなく、自作する必要がある。そういった点で、SPAをするなら、jQueryを使うよりは、Vue、Reactを使うほうが遥かに工数削減ができてメリットがある。

## (3) SPAをしないのであればjQueryを利用するメリットはあるのでは？

　つまり、jQuery不要論は、SPAを作るにあたっての話で、そうでないならば、jQueryは依然として有用なライブラリであると思われる。
　問題は、WebシステムをSPAにしているか否か、また、データバインディングしたコンポーネントを使うか否かではないだろうか。例えば、単純なDOM操作やイベントを少し設定するぐらいならjQueryでも十分だと思う。

　もちろん、SPAの中に、jQueryを使うのも問題はないが、ライブラリの数を抑えるためには不要と思われるものは除外しておくほうがよいのかもしれない。ただ、それは開発者の「好み」に依存するようにも思える。

# 3. SPAを利用するメリット

　SPAは、前述の構成要素を持つが、そのメリットとしては、以下が挙げられる。

- ページ表示に関する通信回数やデータサイズを削減する。
- 上記を通じて、サーバとの通信という描画上のオーバーヘッドを小さくし描画速度を上げる。

# 4. メリットを台無しにするSPAライブラリの利用方法(CSR:Client Side Renderingの速度低下）

　SPAを採用しているが、初回アクセスした際に、真っ白になったり、ローディング画面の表示が長いページがある。
　こういう場合、SPAを利用するメリットを享受していない。
　
　その背景としては、ページ内の構成要素をすべてComponentで、クライアントサイドで描画(CSR：Client Side Rendering）させすぎて、実行時間がかかっているケースもある。

# 5. Pre-Rendering（デプロイ前描画）、SSR（Server Side Rendring）というSPA以前の技術の採用

　CSRの速度改善策として、Nuxt.jsやNext.jsなどを利用したSSR（Server Side Rendering）などがある。要は、ページの要素であるComponentの描画をサーバサイドでしておこうというもの。
　
　また、サーバへデプロイする前にHTML部分を作成するPre-Renderingもあり、これはデータベースなどアプリケーション稼働時に動的なデータ結合を行わずにできる部分において行われる。

　たとえば、ヘッダやフッタなど構成上共通化した部分を各ページごとに結合することなどが代表的だろう。eleventy、Gatsbyなど静的サイトジェネレーターがこうした部分に利用されることがある。

　ここでSPA登場以前に、RailsやLaravelなどのフルスタックWebフレームワークを利用している人からすると、ビューのテンプレートエンジン使っているのと同じではという指摘があると思う。

　強いて、最近のPre-RenderingとSSRの特徴を挙げると、Javascriptベースで作られたComponentを描画するところにある。フロントの要素であるJavascriptで作成されたものを利用しているのが異なっている。

　サーバサイドはJSONを返すAPIに限定し、ビューやフロント側のリソースをサーバサイドと分けて管理するという観点では、JavascriptベースのPre-RenderingやSSRは良いのかもしれない。　

　尤も、RailsやLaravelがもつビューのテンプレートエンジンでSSR部分をしてしまえば、システム構成が少しシンプルになるのではという指摘もあるので、SSRの実現方法については、ソフトウェア実行上の問題よりは、開発方法という人間側の問題になるのではないだろうか。

　ビューの作成やレンダリングの過程について、以下に改めて整理しておく。


## (1) ビュー作成、レンダリングの過程

### a. Pre-Rendring：デプロイ前、コーディング時にHTML作成

　これはヘッダやフッタなど共通部分を分けて作成して、静的サイトジェネレーターなどでデプロイする前にHTMLコードやComponentを作成するもの。HTMLに関して言えばgo製のHugo、Javascript製のものだとeleventy（11ty）、Gatsbyなどのツールがある。これは実行時のデータベースの値などに依存しない箇所には適用できる。


### b. SSR（Server Side Rendring）：DBの値とビューをサーバサイドで結合する。

　アプリケーションが稼働後、ユーザーの操作に関係しない、DBなどサーバサイドで取得できる値とビューを結合する際には、SSRによってビューを作成する。
　ここは、Javascriptのコンポーネントから作成するだけでなく、RailsやLaravelなどWebフレームワークがもつテンプレートエンジンによっても、ビューを作成することができる。
　
### c. CSR（Client Side Renderig)：ユーザーの操作に応じて描画

　ブラウザ上で描画する。多くの場合、ユーザーの操作に応じて描画をする。ここはJavascriptによる描画が必要となってくる。SPAとして尤も特徴を表す箇所。

　
# 6. そもそもSPAにする意味、その適用範囲

　Pre-RenderingやSSRを見ていると、Javascriptによる動的なCSRは局所的なものとなり、SPAの構成要素の扱いも変わってっくる。
　フロントのソースコードは同じだとしても、SSRの仕組みを入れたりすると開発や実行環境での構成要素が変わってくる。
　端的に言えば、それだけ手間が発生する。実際には、コーディング上でも完全なCSRとは書き方が変わる。

　SPAが採用されだした2010年辺りは、2007年にiPhoneの初代が発売され、携帯電話でのWebブラウジングが本格的に普及してきた。当時は、端末自体の性能も低く、通信回線も3G回線(数Mbps～14Mbps)で低速であった。このような状況のなか、SPAにより通信回数を削減し、フロントサイドの描画速度の向上は意味があったかもしれない。

　2020年現在、通信回線は4G回線（75Mbps～100Mbps）になり、SPAが登場した当時より回線速度が5倍強になっている。もちろん、端末の性能も上がっている。
　
　こうしたなか、逆に、Javascriptを多用しない極力静的なサイトに近いほうが表示が速いケースもある。（画像のサイズなどが大きくないなどの条件付き）。

　もちろん、SPAだけが速度低下を招くわけではなく、画像のサイズ、広告など別サイトのAPIへの通信なども関係する。

　いずれにしろ、SPAが採用されだした当時とは、環境も変わっているし、行き過ぎたSPAライブラリの利用は本来のSPAのメリットを台無しにしかねないのではないだろうか。

　SPAの構成要素をみて、CSRにおいて、動的にJavascriptで実現しないといけない部分はどこなのかを改めて検討する必要があるのではないだろうか。


# 7. 局所的なJavascriptによるComponentの利用（Router、State Managerの役割低減）

 SPA登場以前は、ページ描画は頻繁にサーバとの通信が発生しており、それよりは動的に画面を描画したり、必要な箇所だけサーバと通信するSPAの方がユーザー操作の観点ではよいと思う。

　けれど、行き過ぎたSPA化、フルコンポーネント化はどうなのだろうか？

　必要な箇所だけ、Componentを利用し、Javascriptでの管理範囲を下げることで、State Managerの役割も限定可されてくる。

　複数の画面をまたいSPA化にすればするほど、状態管理も複雑になり、コーディングのストレスが発生するのはVuexやReduxを使った事がある人は感じるのではないだろうか。

　SSRなどをみていると、そもそもサイトやページ全体に亘って、JavascriptによるComponentで作成する必要があるのだろうかという疑問があり、実際、そうではないものが多い。

　であれば、局所的に、Componentを利用し、できるだけRouterは排除し、状態管理の役割も居所化シていくのがよいのではないだろうか。

　SPAにおけるComponentという構成要素は、データバインディングを念頭においた時、動的な画面描画にはなくてはならないものであるかもしれない。
　
　その良さは利用しつつも、行き過ぎたSPA化を抑制し、シンプルな構成にして、結果的、通信も描画もシンプルになり、開発者もユーザーのストレスも減るのではないだろうか。

# 8. 部品の再利用をするにしてもHTMLとCSSによるComponentを増やす

　本来、見た目については、構造をHTMLでつくり、装飾・配置・動的効果はCSSでするものであり、Javascriptですら裏側ではこれらを扱っている。

　みてきたようにJavascriptはデータバインディングにその意味があり、それを伴わないコンポーネントは、HTMLやCSSだけで作っておく方が案件を問わず使いやすくなる。（たとえば、あるプロジェクトはVueだけど、別はReactみたいな）
　
　BulmaやPureCSSのようにHTMLとCSSだけでComponentをつくっているものもある。

　Javascriptライブラリの変更頻度とHTML・CSSの変更頻度でいえば、明らかに前者のほうが頻度は高い。
それに、HTMLとCSSはどのようなライブラリを使おうと必ず直接と間接を問わず作成する必要がある。

　つまり一番共通化した技術でComponent、部品を作っておくほうが共通化する意味がぐっと増すように思う。
　
　HTMLとCSSを使ったComponentは、CSSフレームワークでしているようにSassやStylusなどの**CSSプリプロセッサ**ベースやtemplateタグを組み合わせたり、ときに、Hugoやeleventyなどの**静的サイトジェネレーター**と組み合わせることで、管理しやすくなると思う。
　
# 9. 技術選定は、案件規模、再利用性、構成要素、工程など細分化して評価する

　Webシステムを作るなら、Javascript（Typescript)使って、SPAをするのが流行っているそれらの技術を使おうという安易な発想よりは、それが流行った理由、どの工程において威力を発揮するかを細かく評価する必要があると思う。

 また、チームや案件の規模、ソースコードの再利用性などを考える必要もある。小さくて再利用とかあまり考えなくてよいなら、わざわざVueやReactを入れるほうが逆に工数やメンテの際の手間が発生したりする。
　逆に、大規模で部品の再利用をしたり、チームのコードを規制する意味では、VueやReactをいれてコンポーネントを作ったほうがよいと思う。特に、コードを細かく規制するという意味では、Reactの方が適していると思う。

　勿論、分からなければ、とりあえず流行っているものにするというのはありだと思う。けれど、ある程度その道で製造を行えばいろいろなメリットとデメリットが分かる。
　その際には、より細かく物事を整理して評価することが必要ではないだろうか。特に、なんらかの問題がおきているのならば。