なぜ今、ReactをやめてHTMXに戻す動きが出ているのか

フロントエンドの世界では長らく「SPA(シングルページアプリケーション、ページ全体を書き換えずJSでUIを操作する構成)一択」という空気がありました。

しかし2023年12月、Django製フォーラムソフトウェア「Misago」のプロジェクトリードrafalp氏が、React.jsを段階的に廃止しHTMXへ移行するという方針をロードマップに投稿しました[^1]。この事例は、SPA疲れを感じているエンジニアにとって示唆が多い内容です。

この記事でわかること

  • Misagoが抱えていた「二重実装」問題の中身
  • HTMXという技術の仕組みと、なぜこれが選ばれたのか
  • 実際のJSバンドルサイズの変化(実測データ)

結論:サーバーレンダリングに「動的な島」を足すだけで十分だった

結論から言うと、Misagoはページ全体をJSで作り直すのをやめ、必要な部分だけをHTMXでサーバーから差し替える方式に切り替えています。

これによりJSON APIの実装や二重のテンプレート管理が不要になり、実際にJSバンドルサイズも縮小したとrafalp氏は報告しています[^1]。

Misagoが抱えていた「二重実装」問題

Misagoの旧構成は、同じ画面をDjangoテンプレートとReactコンポーネントの両方で作る必要がありました。

具体的な流れはこうです。まずDjangoがHTMLとJSONを同時にレンダリングして返し、その後JSが読み込まれるとJSONを元にReactが同じ内容をHTMLとして再描画します。

rafalp氏はこの構成の問題点を次のように整理しています[^1]。

  • HTMLカスタマイズをしたい人がDjangoテンプレートを編集しても、直後にReactのHTMLへ置き換わり変更が消える
  • ユーザー向け・ゲスト向けの全ページをDjango ViewとReactルートの両方で実装する必要がある
  • 翻訳ファイルがdjango.podjangojs.poに重複して存在する
  • プラグイン開発者もDjangoとReactの両方を理解しなければならない

たとえるなら、同じ設計図を日本語版と英語版で二重に作り、変更のたびに両方を直さなければならない状態です。片方だけ直せば整合性が崩れます。

HTMXとは何か

HTMXは、HTMLの一部を「動的な島」として指定し、ユーザーの操作に応じてサーバーから返ってきたHTML断片で置き換える、小さなJavaScriptライブラリです。

rafalp氏はこれを「20年前にjQueryでやっていた$.get(url, '#outlet')を宣言的に書けるようにしたもの」と表現しています[^1]。RailsのTurbolinksに近い発想とも述べています。

例えば、スレッド一覧でカテゴリを切り替える操作を考えます。HTMXならDjango側は該当のHTML断片だけを返せばよく、JSON変換用のシリアライザやReactコンポーネントを別途用意する必要がありません。

<div hx-get="/threads/?category=2" hx-target="#thread-list" hx-trigger="click">
  カテゴリを切り替える
</div>
<div id="thread-list">
  <!-- ここだけサーバーからのHTMLで差し替わる -->
</div>

Next.js/Remixという選択肢を退けた理由

rafalp氏は当初、2つの案を検討したとしています[^1]。

  1. Djangoの役割を最小限にし、SEO対策用のページだけ残してReact SPA化を進める
  2. DjangoをAPI専用にし、Next.jsやRemix.runでサーバーサイドレンダリングする

しかし最終的にどちらも採用せず、「フォーラムソフトウェアに必要な対話性は、通知確認・投稿への返信・投票・モデレーション操作など、ページの特定箇所に限定されている」という考え方に至ったと述べています。ページ全体をJSアプリ化する必要はない、という判断です。

管理画面についても同様に、既存のDjango View資産(基本ビューを継承しフォームを定義するだけで動く仕組み)を活かす方が効率的だとして、SPA化を見送っています。

段階的移行と実測データ

移行は一度に全部やるのではなく、画面ごとに少しずつ進める方針が取られています。実際にrafalp氏が公開しているmisago.jsのサイズ推移は以下の通りです[^1]。

時期misago.js(素)gzip後
2023年12月(移行前)615kb124kb
2024年6月(Account settings刷新後)578kb107kb
2024年7月(スレッド一覧刷新後)530kb99kb

約半年強で、gzip後のサイズが124kbから99kbまで、25kb(約20%)縮小しています。地道な置き換えでも積み重ねれば効果が出ることがうかがえます。

移行期間中の課題:一時的なMPA化

この移行には過渡期の副作用もあります。rafalp氏は、ReactもHTMXもまだ導入されていない画面では、リンククリックやフォーム送信のたびにフルページリロードが発生する「事実上のMPA(マルチページアプリケーション)」状態になると注意喚起しています[^1]。

ただし、いいねボタンや投票など「リロードが体験を著しく損なう箇所」には暫定的なAjax処理かHTMXを先に入れる方針とのことです。全てを一斉に切り替えず、優先度をつけて段階的に対応している点が実務的だと感じます。

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

日本国内でもDjangoやRailsといったサーバーサイドフレームワークで長年運用している中規模サービスは少なくありません。SPA化の際に「フロント全部Reactで書き直す」という判断をして、後から保守コストの高さに気づくケースもよく聞く話です。

Misagoの事例は、全面SPA化以外にも「必要な箇所だけ動的にする」という選択肢があることを示しています。特にフォーム操作や一覧の絞り込みなど、局所的な対話性しか求められない画面が多いWeb制作案件では、HTMXのような軽量な代替手段は検討の価値があると考えられます。

もちろんMisagoはフォーラムソフトウェアという特性上、対話性が限定的な領域に閉じているという背景もあります。ECサイトのカート画面や、リアルタイム性の高いダッシュボードなど、状態管理が複雑な画面ではReactやVueの方が向くケースも当然あります。

まとめ

Misagoの事例が示しているのは「SPAか、サーバーレンダリングか」の二択ではなく、画面ごとの対話性の必要度に応じて技術を選び分けるという考え方です。

  • 二重実装の負担は、JSON API層とHTML層を両方持つ構成そのものから生まれていた
  • HTMXは「必要な部分だけサーバーからHTMLで差し替える」という宣言的な仕組みで、この負担を減らす選択肢になり得る
  • 実際の移行でJSバンドルサイズが段階的に縮小したことは、地道な置き換えでも効果測定できることを示している

次に新規プロジェクトやリプレイスを検討する際は、「全ページSPA化」の前に、対話性が必要な箇所を洗い出すところから始めてみるのもよさそうです。

[^1]: rafalp, "Removing React.js from the codebase and adapting HTMX for UI interactivity", Misago Forums Roadmap, 2023年12月〜2024年7月. https://misago-project.org/t/removing-reactjs-from-the-codebase-and-adapting-htmx-for-ui-interactivity/1267/