SPAは本当に「正解」だったのか

ReactやVueでSPA(シングルページアプリケーション。画面遷移をJavaScriptで制御し再読み込みなしで動くWebアプリ)を組むのが当たり前になって数年が経ちました。

ですが「本当にここまでJSが必要なのか」と感じる場面が増えている、という声も見かけます。

そんな中、Django製の掲示板ソフト「Misago」が2023年12月、React.jsを段階的に廃止しHTMX(サーバーが返すHTMLの断片だけを画面の一部に差し込む小さなライブラリ)へ移行する方針を公表しました(出典:misago-project.orgフォーラム投稿、2023年12月12日)。

この記事でわかること

  • MisagoがReact.jsで実際に抱えていた技術的な問題点
  • HTMXという技術が何をしてくれるのか、身近な比喩での理解
  • 移行後のJSファイルサイズの実測値と、日本の開発者への示唆

課題:1つの画面を2回作る羽目になっていた

Misagoの問題は「同じ画面をDjangoテンプレートとReactコンポーネントの2つで実装していたこと」に尽きます。

具体的には以下のような問題が挙げられていました。

  • 一覧ページなどがDjango側とReact側で二重実装され、修正漏れが起きやすい
  • ユーザーもゲストも見る画面は、Djangoビュー用とReactルート用を両方作る必要がある
  • React用にJSONを組み立てる処理がレスポンス生成を遅くしていた
  • 翻訳ファイルもdjango.podjangojs.poに分かれ、二重管理になっていた
  • JSの量が多く、特に古いモバイル端末で体感速度が落ちる

プラグイン開発者も、DjangoテンプレートとReactコンポーネントの両方を理解しないと拡張機能を作れない状態でした(出典:同投稿)。

結論:全部をSPA化するのではなく「一部だけ動的に」戻す

rafalp氏(Misagoのプロジェクトリード)が選んだのは、「Reactを全部剥がしてサーバーサイドレンダリング型フレームワークに寄せる」道ではなく、「HTMXで必要な部分だけ動的にする」道でした。

投稿では、掲示板ソフトが必要とするインタラクティブ性は「モデレーション操作」「スレッドのウォッチ」「返信投稿」「通知確認」「投票」など、画面の特定箇所に限られると指摘しています。

これらは20年前のjQueryの$.get()やRailsのTurbolinksでも実現できていた範囲だ、とも述べられています。

HTMXとは何か:テレビのチャンネルボタンのようなもの

HTMXは、HTMLの一部を「動的な島(dynamic islands)」として指定し、ユーザー操作に応じてその部分だけサーバーから新しいHTMLを取得して差し替える仕組みです。

たとえるなら、テレビのリモコンでチャンネルボタンを押したとき、画面全体が真っ暗になって再起動するのではなく、映像だけがパッと切り替わるイメージです。

ページ全体を作り直さず、必要な部品だけをサーバーから取り寄せて差し込む、という考え方です。

Misagoの例では、スレッド一覧のカテゴリ切り替え時に、HTMX経由のリクエストであればDjango側は一覧部分のHTMLだけを返せばよく、JSONのシリアライズもReact用のコードも不要になります(出典:同投稿)。

移行の進め方と実測されたJSサイズ

移行は一気に行わず、リリースごとに少しずつ進める方針が取られました。

ナビバー、スレッド一覧、スレッドページ、ユーザープロフィールといった単位で段階的に置き換えていく、という計画です。

また管理画面についてはSPA化を見送り、既存のDjangoビューの構成をそのまま維持する判断がされています。

rafalp氏は「基底となるビューを選び、フォームを定義し、簡単なテンプレートを書くだけで9割の作業が終わる」現状の管理画面の作りやすさを評価しています(出典:同投稿、2023年12月12日)。

実際のJSファイルサイズの変化は以下の通りです(出典:同投稿、複数日付分)。

時期misago.js サイズgzip後
移行前(v0.39時点)615kb124kb
2024年6月(Account settings刷新後)578kb107kb
2024年7月(Threads list刷新後)530kb99kb

約半年の作業で、gzip後のサイズが124kbから99kbまで縮小したことになります。

また移行途中では「Reactもなければ HTMXも入っていない、素のマルチページアプリケーション状態」の画面が一時的に発生することも予告されています(出典:同投稿、2023年12月16日)。

日本の開発者にとっての意味

日本の受託開発やコーポレートサイト制作の現場では、DjangoやRailsのようなサーバーサイドMVCフレームワークに、部分的にReactやVueを載せる構成がまだ多く見られます。

Misagoの事例は、その「部分導入」で発生しがちな二重実装・翻訳ファイル分裂・JS肥大化といった問題が、実際のプロダクトでどう表面化するかを具体的に示している点で参考になります。

また「フル SPA化」と「フルSSR回帰」の二択ではなく、HTMXのような軽量ライブラリで必要な箇所だけ動的にする第三の道があることも、構成検討の選択肢として押さえておく価値があります。

Django・Rails・LaravelなどサーバーサイドHTMLレンダリングが主体のプロジェクトでは、特に相性を検討しやすい技術だと言えそうです。

まとめ

Misagoの事例からは、以下の点が確認できます。

  • Reactとの二重実装は、開発規模が大きくなるほど翻訳・API・ビルドの負担として蓄積する
  • HTMXは画面の一部だけをサーバーHTMLで差し替える設計思想で、SPAほどの複雑さを持ち込まない
  • 実際の移行では約半年でgzip後JSサイズが2割減という数値が出ている(出典:同投稿)

全面SPA化に疲れを感じているなら、Misagoのように「必要な場所だけ動的にする」設計を検討してみる価値はありそうです。