header

SPAはコストが高いのか

なぜ僕が「SPAはコストが高い」と考えているのか を読みました。 「反論お待ちしています」とのことなので、書いてみます。

結論としては、 コストが低いのは慣れているほうだよ。 どっちも使えるならSPAのほうが低いよ。 です。

前提

元記事で挙げられている前提をまとめます。

  • 用語
    • SPAとは、クライアント側でビューを構築する方式を指す
    • MPAとは、サーバ側でビューを構築する方式を指す
  • 背景
    • エンジニアのスキルはあまり高くない
    • 開発期間は1.5年未満
    • PMFを意識したフェーズであり、チャレンジを繰り返す
    • ログイン機能が存在するサービスを作る
  • コストの定義
    • エンジニアの採用のしやすさ
    • サービス開発の 初速
    • サービス開発の 継続性
    • 分業のしやすさ、手伝ってもらいやすさ
    • web標準の挙動の実現のしやすさ
    • セキュアなデータを流出する可能性の高低
    • バグがあった時の気づきやすさ / 対応のしやすさ
    • ドキュメントの多さ
  • 元記事の筆者の技術歴
    • Railsを約11年
    • Reactを約5年
    • その他
      • 業務でNext、Nuxt
      • 趣味でRiot、Svelte

参考までに私の技術歴は以下の通りです。

  • SpringとPlayを同時期に約3年ずつ
  • Vue/Nuxt を約4年
  • その他
    • 業務でLaravel、Django、Flask、React/Next
    • 趣味でPhoenix

「3. web標準の挙動の実現のしやすさ」について

zenn.devさんでも「Popular Topics」→「○○をもっと見る→」を押した後に戻るボタンを押すとスクロールバーの位置がおかしくなる~と言ったバグがあります

こちらはSPAではなく要件の問題です。 画面の一部を非同期で取得していることが原因です。 そのような要件がなければ発生しませんし、逆にあるのであればMPAでも発生する可能性があります。 MPAではそのような要件は生まれない、もしくは生まれたとしても対応しないのであればたしかに発生しませんが。

ちょっと前ですがpixiv sketchさんでもログインして戻るボタンを押したらログインしてないことになってバグる~とかありました

詳細がわからないので推測になりますが、ログインしているのにログイン画面が表示されてしまうということでしょうか? それであればSPAではなくルーティングの問題です。 SPAかMPAかによらず、認証状態に応じたルーティングを行わなければ発生します。 どちらであってもその実装コストは変わりません。

ブラウザバック関連だと、逆にMPAのほうがコストがかかるケースもあります。 たとえば以下のようなフローです。

  1. ページAからページBに遷移する
  2. ページBのフォームに入力して送信する
  3. サーバ側でエラーが発生し、クライアントの画面上にその旨が表示される
    • たとえばユニークな項目に重複する値を入れた場合など
  4. ブラウザバックでページAに戻ろうとすると、ページAではなくフォームを入力する前のページBに戻ってしまう

MPAだと2.と3.の間でページ遷移しているために発生する問題です。 SPAであればレスポンスを受けてからページ遷移できるので発生しません。

「4. セキュアなデータを流出する可能性の高低」について

元記事の主張は以下のような内容です。

MPAではサーバ側でデータを埋め込んだビューを構築してから返すので、通信時に不要なデータが含まれない。 SPAではサーバからデータを受け取ったあとにビューを構築するので、通信時に不要なデータが含まれる可能性がある。

こちらもSPAの問題ではありません。API設計の問題です。 元記事ではOpenAPIを導入するコストがかかると書かれていますが、不要です。 API側でレスポンスに型を付けるだけで良いです。 単体テストを書くだけでも良いです。

このあたりはむしろMPAのほうが怖いと思っています。 SPAではAPIが境界になっているので、そのインタフェースのデータしか通信されない安心感があります。 しかし、テンプレートエンジンを使った場合は、サーバ側のすべてのデータについて埋め込まれる可能性があります。 しかもほとんどのエンジンは型で守られていません。

ちなみに元記事にはSPAで起きた事故の例が貼られていますが、仮にSPAで事故が多かったとしても、それはMPAで事故が少ないことを意味しません。

「5.バグがあった時の気づきやすさ / 対応のしやすさ」について

SPAはその性質上エラーがクライアントサイドで発生するのでエラーハンドリングをするためにも知識が必要となります

いや、わかりますよ?sentryでも入れれば良いだろ?って話だと思います。でもそれもまたスキルが必要です。今回想定しているような層はそもそもエラーハンドリングなんて概念がないと思いますし、何もしなくてもエラーが起こったらサーバーサイドにエラーログが残るというシンプルな仕組みのほうがコストが低いと思うわけです

SPAにもサーバサイドはありますし、MPAにもクライアントサイドはあります。 SPAがAPI側でエラーを起こさないわけではないですし、MPAがクライアント側でエラーを起こさないわけでもないです。 SPAはクライアントサイドの処理が多くなるので、その分だけエラーに気づきにくいという意味であればその通りだと思います。

ただ、SPAは TypeScript を使うことでビューも型で守れるようになるので、バグ自体を減らすことができます。 前項の通り、ほとんどのテンプレートエンジンでは守れません。

サーバー→フロントに分離していることでエラーがどこで起こっているのか分かりづらかったりなどの問題もあります

こちらに関してはむしろ分離されているほうが分かりやすいと思います。

「6.ドキュメントの多さ」について

こちらはSPAではなくフレームワークの問題です。 元記事ではQiitaのタグ検索でヒットする記事の件数を根拠としています。

  • Laravel
    • 約10,000件
  • Rails
    • 約35,000件
  • Next.js
    • 約1,500件
  • Nuxt
    • 約3,500件

他のMPAのフレームワークを検索してみましょう。

SPAだから少なくてMPAだから多いわけではないです。 LaravelとRailsが特別なだけです。

まとめ

以上、SPAはMPAと比較してコストが高いわけではなく、むしろ低いケースもあることを書きました。

クライアント側はサーバ側よりも変更されやすいので、クライアント側を修正しやすいSPAを使うとコストが低くなるという観点もあります。 背景が「PMFを意識したフェーズであり、チャレンジを繰り返す」なのであればなおさらですね。 この点に関しては、「サービス開発の継続性」はSPAのほうが低コストと元記事でも書かれている通りです。

「エンジニアのスキルはあまり高くない」という前提に、「SPAよりもMPAの経験のほうが長い」を暗黙的に含んでいる気がします。 SPAの経験のほうが長い私にとっては、逆にMPAをコストが高いと感じます。 慣れている技術を優先しつつ、どちらも使えるならSPAを使うのが良いのではないでしょうか。

追記

はてブでいただいたコメントに返信していきます。 個人ブログで初めてコメントをいただけたのでありがたいです。

coppieee いやーエンジニアのスキルが低い場合の前提だから、「コストが低いのは慣れているほう」では反論になってないでしょ。学習コストの話しないと。

「『6.ドキュメントの多さ』について」がまさに学習コストの話です。 学習コストとして考えるべきなのはそれだけではない、という意味であれば元記事も同じです。

fai_fx 〇〇はSPAの問題ではない。それは当然の話で、〇〇が起きた時に、SPA/MPAのどっちが解決が速いかが、考えるべきコストなのだと思う。

SPA/MPA で差がある問題であればその通りですね。 差がなければどちらが速いとかはないと思います。

今回の論点の中で差があるのは「『4. セキュアなデータを流出する可能性の高低』について」と「『5.バグがあった時の気づきやすさ / 対応のしやすさ』について」ですね。 前者はSPAのほうが低コストであることを書きました。 後者はSPAのほうが高コストですが、完全に劣っているわけではなく、SPAが優れている点もあることを書きました。

cpw 必要な観点が抜けている。開発するアプリのサイズ、複雑度、特性、開発者の能力を考慮して決めないといけないと思う。極端な話時刻を表示するだけのアプリにSPAは使わないしね。あと、バージョンアップも考慮必要

サイズと複雑度は、PMFを意識したフェーズとのことなので、小さめです。 元記事にはMVPで作り捨てであることも書かれています。 この条件であれば正直どちらでも良いので、慣れているほうですかね。

特性は、元記事で触れられていなかったのでこちらでも触れていないのですが、重要な観点だと思います。 細かく考えるとそれだけで1つの記事が書けるので、ざっくり箇条書きにしてみます。

  • SPAが有利
    • 画面の一部を動的に変える
      • ページ遷移せずに検索結果を表示する、段階的開示やチュートリアルを用意する、チャットやゲームを作るなど
    • 複雑なアニメーションがある
      • ページ遷移時にトランジションエフェクトを入れるなどは、MPAだと不可能
  • MPAが有利
    • SEO対策をする
      • どこまで有利かは不明

このあたりは私も他の方の意見をお聞きしたいところです。

開発者の能力は、あまり高くない前提とのことです。 慣れているほうが有利ですね。

バージョンアップのコストは、SPA/MPA というよりフレームワークの問題ですね。 当然枯れたものを使うほど楽になります。

ちなみに、時刻を表示するだけであれば、HTMLファイル1枚の中にJS/CSSを書くのが一番コストが低いので、SPAともMPAとも言えないですね。

xlc Google MapやCalenderを実装するならともかく、FORMの入力ばかりの業務アプリをSPAにするのは愚か。業務アプリという「つまらない」世界に閉じ込められた有能とは言えないエンジニアが有能ぶるために手を出してるのが実情。

段階的に入力するフォームであれば、SPAにすることでUXが向上するので、要件によると思います。

Error401 MPAの各ページをSPA的に実装するのが最もコストが低いと思う

おっしゃる通り、一般的な SPA/MPA の定義では、MPAでもReactやVueなどのJSフレームワークを使うことがありますね。 上に書いたように、画面の一部を動的に変えたいときはそれらを使うことでコストを低くできるためです。 その際はwebpackの設定を頑張ることになります。 私もやったことがありますが、個人的にはMPAではなくSSRにしたほうが楽でした。

ただ、前提の項にも記載しましたが、元記事ではJSフレームワークを使うのがSPA、それ以外をMPAと定義しているんですよね。 この記事ではそちらにそろえています。