先日管理画面系のサイトをリニューアルするにあたり、SPAを検討しました。その過程で何を検討し、どう判断したのかを書いてみたいと思います。

検討するサイト

まずは検討対象となるサイトについて説明したいと思います。
いわゆる管理画面サイトで、左側はサイドメニュー、右側はコンテンツエリアの2カラムレイアウト。サイドメニューの項目をクリックすると各ページのコンテンツが表示されます。
ヘッダー部分にはログイン情報があります。

コンテンツ・機能としては、以下のような物があります。

  • 項目リスト表示
  • 項目詳細表示
  • 項目編集
  • 項目追加
  • ログ表示
  • カレンダー・タイムテーブルによるタスク管理
  • 設定画面
  • ダッシュボード

バックエンドはASP.NET MVC。タスク管理機能など動的な部分はjQueryで実装しています。
SEOは必要ありません。モバイルアプリもありません。モバイルではPC版のレイアウトで操作できればOKなのでレスポンシブでもありません。

SPA、MPAの定義

SPA、MPAという言葉を多用するので、言葉の定義をします。

Single Page Application(SPA)

1つのページだけで構成されるサイト。ページ遷移がない。すべての動的コンテンツはAJAXで取得し、DOM更新する。ブラウザのヒストリーAPIを使って「ページ切り替えのようなこと」はできるが実際にはページ遷移していない。

Multi Page Application(MPA)

複数のページで構成されるサイト。ページ遷移を行う。ページの一部をAJAXなどを使って動的に更新することはできるがページ遷移するとページ全体を再表示することになる。SPAの対比のために使う。

リニューアルの要件

サイトをリニューアルするにあたり、以下の要件がありました。

  • デザインを新しく作り直す。(かっこいくておしゃれなやつ!)
  • タスク管理等の現在jQueryで実装している動的な部分も、ReactやVue等の最新のビューライブラリで書き直す。

SPAを検討した背景

ここ1,2年で、SPAの記事を目にすることが増えてきました。この時点ではSPAサイトを自分で作ったことはありませんでした。自分の中でSPAに対して抱いていた印象や知識は以下の様なことです。

  • ページ遷移がないので通信量が削減できる
  • ページ遷移がないので通信が発生せず、デスクトップアプリのようにキビキビ動く
  • バックエンドからUIロジックを排除できる
  • PCサイトとモバイルアプリで1つのバックエンドを使いまわしできる
  • JSファイルが大きくなるので初回ロードが遅いかも
  • SEOが不安なのでメディアサイトには向かないかも
  • それなりのフロント技術を求められるよ!

この中で一番魅力を感じたのは2番目のデスクトップアプリのようにキビキビ動くという点です。通常のWebサイトではページ遷移すると通信が発生するので、コンマ何秒かの待ち時間が発生します。これがなくなるのは地味だけど、でも体感できる差です。大きな差別化要因になると感じました。

「デスクトップアプリのようにキビキビ動くこと」は要件にはないですが、もしそれが実現できればそれに越したことはありません。そこでSPAについて詳しく検討することにしました。

検討したこと

以下、それぞれ検討したことと、その結果になります。プラス1なら☆(+1)、プラス2なら☆☆(+2)、マイナス1なら★としてランク付けしていきます。合算して☆が多ければ費用対効果があります。

検討にあたっては実際にAngular2でSPAサイトを構築してみました。

☆ページ共通部分を更新しなくていいのでその分高速化できる

SPAではサーバーは「データ」、フロントは「UI」と役割分担しますから、フロント側では必要な部分のみUI更新することができます。そうするとページヘッダーやナビゲーション部分はページ切り替え時には更新する必要がなくなりますからその分のレンダリングや通信コストが削減できます。これは正しいのでしょうか?

例えばログページから設定ページに移動した場合を考えてみます。

MPAの場合、

  1. ブラウザからページHTMLを要求
  2. サーバーでページ全体をレンダリングしてHTMLとして返す
  3. 返ってきたHTMLをブラウザで表示

SPAの場合、

  1. ブラウザから設定値をAJAXで要求
  2. サーバーで設定値をJSONで返す
  3. 返ってきたJSONをクライアントでDOM更新

上記を考えてみると、MPAはページ全体を送っているのに対して、SPAでは設定値だけを送っています。たしかに通信量は削減できそうですね。しかし体感できる程の差かどうかは、ケースによるのではないでしょうか。

今回のサイトの場合、ページ全体のHTMLは30KB程です。設定値のJSONが1KBだったとして、その差は29KBになります。29KB削減の効果は疑問です。モバイル環境なら大きいでしょうが、モバイルは想定していません。でも削減できるのはいいことですね。効果は小さいかもしれませんがプラス材料です。星ひとつ。

☆ページ遷移がないので通信が発生せず、デスクトップアプリのようにキビキビ動く

SPAはデスクトップアプリのようにキビキビ動くのが魅力です!この最大の利点を得るためにSPAにするといっても過言ではありません。
では管理画面をSPAにするとどうなるでしょうか?

前項の例を見てください。

あれ?どっちも通信発生していますね。SPAってページ遷移がないから早いんじゃなかったの??

通信が発生するということはMPAと同じく通信待ちが発生するということです。デスクトップアプリのようにキビキビ動きません。

SPAではキャッシュするから2回目以降はAJAXも要らないということでしょうか?ん?設定値をキャッシュする?それじゃ設定値が最新のものじゃないかもしれなくなるってことだからダメだよね。

設定ページ以外ならどうだろう。ログも最新じゃないと困るし、他も全部最新がいい。でも例えばログのページ送り操作のケースを考えると、クライアントサイドでキャッシュしてくれてもいいような気がする。その場合は通信がなくなるのでキビキビ動きますね。そっか、コンテンツによってキャッシュすべきかどうか違うんだ。で、キャッシュできないものはゼロ通信にできないと。

結局、SPAにしたからといって一律にゼロ通信にはできない。これじゃあデスクトップアプリにはなれない。当初期待していた目論見が崩れました。考えてみれば当たりまえの話ですが、大きな勘違いをしていたようです。

とりあえず、キャッシュできる場面ではキビキビ動くということで星ひとつ。

★初回は全ページのテンプレートを取得するため大きくなる

SPAはJSファイルに各ページのテンプレート、UIロジック、スタイル情報なども含めるため、ファイルサイズが大きくなりやすい。

初回表示が遅いってやつですね。ファイルを分割するなど工夫が必要になるかもしれません。マイナス星ひとつ

★★★ページキャッシュが使えない(戻る・進む問題)

これは実際に作ってみて気付いたことですが、SPAはブラウザのページキャッシュ機能が使えないんですね。

どういうことかというと、例えばログページから設定ページに移動した後、戻るした場合を考えてみます。

MPAの場合、

  1. ブラウザのページキャッシュからログページHTMLをロードして表示

SPAの場合、

  1. ブラウザの戻るイベントを受け、クライアントJSがログページのテンプレートをロードして表示
  2. クライアントJSがログデータをAJAXで要求
  3. サーバーがログデータをJSONで返す
  4. 返ってきたJSONをクライアントJSでDOM更新

MPAでは最終的なHTMLがブラウザのページキャッシュとしてローカルに残っていますから、それを表示するだけです。しかしSPAの場合はこのページキャッシュ機能が使えないため、自前ですべて賄う必要があります。対策としてはログ結果を自前でキャッシュしておき、戻る・進むの場合はキャッシュを参照するようにすることだと思いますが、MPAではブラウザがすべて面倒をみてくれる点と比べると気が重くなります。

これは当初想定していなかったデメリットです。管理画面系サイトはページ切り替えが多く、戻る・進むは普通に使います。マイナス星みっつ。

まとめ

他にも検討課題はあったと思いますが、この時点で今回のケースではSPAの採用を取りやめました。一番期待していたデスクトップアプリのようなUXが得られないと分かったからです。

おそらくSPAの使いどころというのは以下の点が判断条件になってくるのではないでしょうか。

  • サーバーからのデータ取得伴わない操作が多いか
  • サーバーからのデータ取得をキャッシュしやすいか

SPAにしろ、デスクトップアプリにしろ、データがリモートにある以上、通信待ちからは逃れられません。データをローカルに置けるというのはUI速度という面では利点です。データをリモートで一元管理できるというのもまた別の利点です。どちらも、ということは簡単ではありませんね。

ということで、以上となります。いかがでしたでしょうか?少しでも参考になれば幸いです。