💾

Reactは悪い意味でも現在のjQueryだし、それを受け止めないと前に進めないということ

2024/03/17に公開
5

HTMXのCEOに就任したので[1]、記念に記事を書きたいと思います。
HTMXサイトのエッセイ[2]はどれも珠玉の出来で評判ですが、それらを読んでもわかるとおり、HTMXは「Webはこうあるべき」という主義主張のあるライブラリです。その主義主張のかなり初歩的な前提を書きたいと思います。
Reactはなぜだめか、という話です。


21日追記

ちょっと誤解が生じているために書き足しますが、Reactのパフォーマンス(及びそれ以外のこと)への批判というのはHTMX固有のものではありません。SvelteやSolidJSといった新興JSフレームワークやRails等の非JS WEBフレームワーク、SSG開発者たち、それからReact開発者たち自身といった多様なWEB開発者たちに共有されている見方です。この記事の最後の方でReact批判記事のリンク集を引用していますが、そういった多様なバックボーンの人たちによって書かれています。


jQuery

昔話から始めますが、ぼくが街のホームページ屋さんを生業としてやり始めたおよそ10年ぐらい前、ES6によって”Web標準”への道が開けつつあり、標準化されていないJavaScript仕様を埋めるためものであったjQueryはすでにイケてない存在になりつつありました。
ReactやVueなどのコンポーネントUIライブラリは来つつある未来だったのです。

当時、jQueryは「サイズが大きくてパフォーマンスが悪い」ものとして厄介払いされようとしていました。
bundlephobiaによると[3]、ミニファイされたjQueryのバンドルサイズは85.1kb、GZIPされたものは29.7kbです。読み込みまで遅い3G回線なら0.59s、4G回線でも34msかかるそうです[4]。ゲームをやられる方ならわかるでしょうが、人間は10msを超えれば遅延を感じるようになるそうです。ゲームとWebサイトでは違うでしょうが、読み込みまでに体感で感じられる時間はありそうですし、おそらく実際にその時間を経験したこともあるでしょう。
当時のjQueryに対する批判は、まあ、いわれなきものではなかったと思います。

React

現在いちからWebサイトを作ろうとするなら、フロントエンド開発者ならNext.jsなり、RemixなりReactのフレームワークを立ち上げて作るでしょう[5]。しかし、そうするとなんと、10年前のJQueryをCDNで読み込んだサイトと似たような問題を抱えることになります。
Reactは「サイズが大きくてパフォーマンスが悪い」です。

Reactを使うときはreact-domを一緒に使います。bundlephobiaによると[6]、ミニファイされたreact-domのサイズは130.2kb、GZIPされたものは42kbです。読み込みまで遅い3G回線なら0.84s、4G回線で48msかかるそうです。
この記事を書くために調べてちょっと驚きましたが、ReactはjQueryよりも重いのです[7]

「バンドルサイズだけがパフォーマンスを決定するのではない」と言われる向きもいるでしょう。
また昔の話になりますが、ReactやVueが脚光を浴びはじめたころに「DOM操作なんてイケてない手法に対し、ReactやVueは仮想DOMというやつのおかげでとても早いらしい」なんて話をよく聞きました。
DOM操作は本当にイケてないにしても、現在では「仮想DOMは純粋なオーバーヘッドに過ぎない」という意見すらあります。そこまで言い切れるかどうかはぼくに判断のつく話ではないですが。
これはReactの対抗馬として、SvelteやSolidといった仮想DOMを使わないライブラリが頭角を現してきたからです。これらのライブラリはバンドルサイズがはるかに小さく、パフォーマンスがとても良いです。VueもVaporモードという仮想DOMを使わない実装のリリースを控えています。

実際のところ、Reactコミュニティにおいても、パフォーマンス問題というのはかなり意識されていると思います。Million.jsやReact19での自動メモ化機能など、Reactのパフォーマンスを解決するための手段というのはホットなトピックです。
しかし、パフォーマンス問題を本当に解決できるかという根本的なところも含めて、現在のReactは過渡期にあるといってもいいでしょう。

他にもReactに関する問題はいろいろとありますが、フレームワーク(特にNext.JS)やSPAなど純粋にReactだけではない論点が絡んでくるので、ここでは論じきれません。この記事では代表的なところでパフォーマンス問題だけ扱うことにしました。
興味があれば、英語ですが、以下の記事と以下の記事からのリンクを読んでみてください。ぼくごときの言うことが信じられない場合でも、それらの記事を書かれている方たちは超一流の開発者たちなので、論拠としては十分だと思います。

Please don't use React · Já não vou salvar o mundo (borfast.com)

  1. The Market for Lemons
  2. The Great Gaslighting of the JavaScript Era
  3. We tried that, didn’t work
  4. Web developers: remarkably untalented and careless?
  5. Things you forgot (or never knew) because of React
  6. A Historical Reference of React Criticism
  7. Rethinking the Modern Web
  8. Taylor Otwell: Avoid Separate SPAs consuming Laravel API. Use Livewire/Inertia.
  9. The self-fulfilling prophecy of React
  10. What Got Me Writing Vanilla JavaScript again
  11. The AHA Stack
  12. Removing React is just weakness leaving your codebase
  13. Kind of annoyed at React
  14. React, where are you going?
  15. The deciline of React
  16. Concatenating text
  17. The (extremely) loud minority

「Reactを使うな」とまで言い切る気はないのですし、言い切れるほどのアレもないのですが、これらの問題はWeb開発者であるならば、ちゃんと受け止める必要があると思います。
でないと、我々は自分たちでも問題を抱えているとわかっているものをクライアントに「現在Webサイト(なりWebアプリケーション)を作る唯一の選択肢です」といって提示するしかないということになります。
それは問題です。まったく問題です。

以上を持ちまして、私のHTMX CEO就任記念とかえさせていただきます。
というわけで皆さん、HTMXを使いましょう![8]

脚注
  1. HTMX CEO's ↩︎

  2. </> htmx ~ Essays ↩︎

  3. jquery v3.7.1 ❘ Bundlephobia ↩︎

  4. 公正を期すために書いておきますと、bundlephobiaの想定は日本の回線事情に比べるとかなり遅いと思われます。しかし、世界の回線事情がどこも日本のように恵まれているわけではありませんし、常に光回線でルーターから直接モデムに繋いでいるのでない限り(繋いでいても)、我々の回線がその速度になることはあり得ます。私は楽天モバイルユーザーです。 ↩︎

  5. Reactのドキュメントでそう推奨されています。React プロジェクトを始める – React ↩︎

  6. react-dom v18.2.0 ❘ Bundlephobia ↩︎

  7. Vueも同じです。 ↩︎

  8. ここからさらにHTMXにつなげるには先に挙げたSPAの問題等が絡むので手に余ります…… ↩︎

Discussion

makoto-developermakoto-developer

個人的にはRemixが主流になりそうでまだなってないような…そんな気がします。
https://remix.run/

オトワオトワ

ちょっとフレームワーク編のネタバレをしますと、Reactのメンテナは多くがVercelに雇用されており、「NextJSがReactを食っている」状況があります。React新ドキュメントのフレームワーク推奨やNextJSのReact Server Components先行実装もそのような状況の現れだと思います。
NextJSはVercel以外ではフル機能が使えない(とドキュメントで謳っている)ことや、他のフレームワーク開発者からのVercelからの協力の少なさへの不満など、ReactのVercel化というのはベンダーロックインの兆候があります。
開発の主体からMetaからVercelに移る上で、新興テック企業にありがちな起業以来いまだに利益を上げられないVercelが本当に維持できるのか、という話も……

それと、Remix自体はそうでもないですが、ただでさえ複雑なReactがフレームワークを使うことで更に複雑になるということへの疑問の声も大きいです。JSだけ全部組ませるのにどんだけ複雑になんねん、と。これはRubyとかJS以外のフレームワーク開発者からが多いですね。「JS産業複合体」という悪口もあります。

一応、記事内のリンクと以下の記事がソースです。

https://www.epicweb.dev/why-i-wont-use-nextjs

Ken OkabeKen Okabe

https://zenn.dev/y_ta/articles/1eb1403af45909

という記事について批判的なコメント群を投稿した者としてコメントします。

なんでこの記事に100近くも高評価がついているのかもよくわからないです。
https://htmx.ceo/
という、なにかよくわからない釣りサイト?で偉い人だ!みたいな反応でしょうか?プログラミングスクールなどで流入人口も増えたのかも知れませんがWebフロントエンド界隈の人的技術的脆弱性を感じざるを得ません。

Reactは現在のjQueryだ
理由「サイズが大きくてパフォーマンスが悪い」
という主張であるようです。

まず、バンドルサイズによるロード時間と、仮想DOMやらによるパフォーマンスとは、全く別の技術的要素です。

「バンドルサイズだけがパフォーマンスを決定するのではない」と言われる向きもいるでしょう。

「だけ」も何も、諸般の事情で緩い相関関係は否定できないものの、「でかいライブラリならば動作速度は遅い」「小さいライブラリならば高速に動作する」なんてプログラムやってる人ならば初歩の初歩レベルで呆れ返る理屈でしかありません。

これはReactの対抗馬として、SvelteやSolidといった仮想DOMを使わないライブラリが頭角を現してきたからです。これらのライブラリはバンドルサイズがはるかに小さく、パフォーマンスがとても良いです。

とありますが、「パフォーマンスがとても良い」理由は仮想DOMの差分計算を回避している工夫が凝らしてあるからであって、ライブラリのバンドルサイズの小ささとは何の関係もありません。

これについて説明します。

jQueryからReactは、命令型から、宣言型あるいは関数型への大きなパラダイムシフトがありました。

Reactにおいてはパフォーマンスについては遅くなっていたのに、一部では「なぜ仮想DOMという概念が俺達の魂を震えさせるのか」という大げさなタイトルの記事が注目を集めており、そこでは

なぜVirtual DOMか 結論から言うと、「設計と速度が両立する」

と主張されていました。また、

HTMLとはツリー構造であり、2つのツリー構造のdiffを算出して、それをDOMにpatchするアクションを作れば、常に最小のコストで状態遷移を表現できるよね、ってのがVirtual DOMという発想のスタート地点となります。

この方式はむしろパフォーマンス、コストを気にしない、無視できれば、クリーンでシンプルな設計で良いです。

トリッキーなのはここで「常に最小のコストで状態遷移」させるための 「2つのツリー構造のdiffを算出」の計算コストが大きい ということで、SvelteではコードをコンパイルしてリアルDOMだけのコードに最適化することで計算コストを下げ、SolidJSでは、さらにいろいろ工夫

https://dev.to/ryansolid/thinking-granular-how-is-solidjs-so-performant-4g37

しています。

従って、現代的な知見からすると、まあこの仮想DOM推しで高速の主張については大きな疑問符がついて当然なので、さすがに著者ご本人は自己フォローのようなこともしておられるようです。

https://zenn.dev/mizchi/books/0c55c230f5cc754c38b9

その記事の冒頭にも少しだけ触れられていますが、これは、根本的には、オブジェクト指向のMVCが破綻して、関数型プログラミング、もっといえば関数型リアクティブプログラミングにパラダイムが移行したのです。

もちろん、オブジェクト指向VS関数型という言葉を使うと、特にサンクコストの呪縛から逃れられないオブジェクト指向信奉者は感情的な反発があり、関数型信奉者は無用に難解な言葉でマウンティングを取ろうとし、揉め事、宗教戦争になるのがデフォルトなので、FacebookのReactでは本質的には関数型が正解なのに、この概念を周到に避け、宣言型 という言葉を使い、Reactというライブラリ名であるにも関わらず、関数型と表裏一体の Reactive の概念はろくすっぽ説明されず stateimmutable という概念だけで通そうとしていました。

というより、一時期、ES6とともに時代に逆行したClassコンポーネント実装をデフォルトにして大失敗した挙句、Hooksという関数コンポーネントへ軌道修正したところをみると、本当にFacebookの技術者が事の本質を理解していない可能性すら否定できません。

jQuery自体も当時の劣ったDOM操作のAPIの関数型的抽象化を試みたライブラリであったのですが、その反省から現代のモダンなDOM操作用APIではわざわざjQueryつかう必要はなくVanillaJSで書こうというのが現代的なアプローチです。

https://youmightnotneedjquery.com/

いずれにせよ、jQueryがあろうとなかろうと、DOMをHTML側で組んで、それをターゲットにし、そこにJavaScriptのAPIで命令して操作していく、という命令型と、HTML側はすっからかんで1個のROOTだけ宣言して、JavaScriptではゼロから関数型コンポーネントで全部UIを構築するという宣言型の大きな違いがあります。

さらに、仮想DOM とかいうのは、宣言型UIの実装のひとつの方法でしかない、ということが、特にリアルDOMしか使っていないからこそ高速なパフォーマンスを叩き出すSolidJS以降ではっきりと証明されてしまいました。

つまり、なぜVirtual DOMか 結論から言うと、「設計と速度が両立する」
というのは、技術の試行錯誤の末の実験結果からは、事実とはまったく逆の主張をしていた、ということが後世の実装で示されてしまったわけです。

そして、現状もっとも洗練された実装は、

https://vanjs.org/

でしょう。
リアルDOMで、しかもSolidJSのようにJSXも使っていないのでトランスパイルすら不要の小さなライブラリです。

バンドルサイズでいえばグラフでご覧の通り極小ミニマルのUIライブラリで、ReactはもとよりSolidJSよりも比較にならないほどサイズは小さいです。

しかし、パフォーマンスで比較すると現状SolidJSが最速で、VanJSのほうが遅くなります。

Reactは悪い意味でも現在のjQueryなぜならバンドルサイズが
という主張は前述のとおり初歩レベルで間違った主張であり、大局的なパラダイムの視点からも間違っています。

では次に来るのはHTMXだ、との主張ですが、これはまあVueの再来でしょうね。いつか来た道、同じ間違いを繰り返す、です。

HTMLでなく、JavaScriptのほうでDOMはファーストクラスオブジェクトとしてComposeして行くという関数型シフトについていけない、そのついていけなさを正当化したい人らの一時的な精神的平安をもたらすかもしれないエスケープルームみたいなものです。

自分は、React、これはこれで出来はけして良くない関数型ライブラリではあるのですが、そこから逃げた人たちがVueに群がっているのを見て、どうせこれは長続きしない、と思っていました。

ReactのAPIは無用に複雑で難解なので(同じことができてシンプルでより高速なVanJSをみれば意味がわかる)逃げたくなる気持ちは理解します。

しかし、その結果、今度はHTMLのほうでコードを書く、と見てぞっとしましたが、

https://htmx.org/examples/edit-row/

このサンプルコードの特に、長大なJavaScriptコードが緑の文字列でベタ書きされている HTMXコードを閲覧して、やっぱりぞっとするしかなかったです。不可避。

JavaScript不要で簡潔にシンプルに書ける、などと喧伝しているのは、極めて初歩的なアプリケーションに限定されていて、ちょっと普通にUIが複雑になった途端にそのシンプルさは破綻することは案の定すぐに確認できました。

ちょっと複雑になればコードが加速度的に複雑になるのはVueも同じで、なんでそんなすぐに破綻するのか?というと、単に

何が何でもHTMLのほうで書く(たとえJavaScriptに依存してでも!)

という自己矛盾した設計思想だからです。
なんでこんなことが起こって、しかも持ち上げられているのか、正直なところ、自分にはさっぱりわかりません。

逆に宣言型UIの、DOMを単にJavaScriptという言語内で他のすべての値と同じように、値として一律に統合して取り扱う、DOMはファーストクラスオブジェクト
にすぎない、という設計はそんな難しいんでしょうかね?

まあDOMをHTML表記そのままのJSXというのは、気持ち悪い、というのは基本理念がわからないとそうなのかもしれません。JSXなのでVanillaJS
へトランスパイルが必要ということも拒絶感もあるんでしょうが、それならHTMXのほうがよほど奇妙だとも思うし、あと仮想DOMがあたかも技術的本質であるかのような前時代の間違った説明も負担になったのかもしれません。

ならやっぱり、JSXじゃなくて、VanillaJSで同じようにDOMをファーストクラスオブジェクトとしてComposeするVanJSならそこの気持ち悪さは消えるのかな?と期待はしています。

// Reusable components can be just pure vanilla JavaScript functions.
// Here we capitalize the first letter to follow React conventions.
const Hello = () => div(
  p("👋Hello"),
  ul(
    li("🗺️World"),
    li(a({href: "https://vanjs.org/"}, "🍦VanJS")),
  ),
)

van.add(document.body, Hello())
// Alternatively, you can write:
// document.body.appendChild(Hello())

あと、Reactは仮想DOMだろうとSolidJSやVanJSなどの後継ライブラリのリアルDOMだろうと、DOMをファーストクラスオブジェクトとして統合した、という思想的功績は大きいと思います。

ただ、逆に言うとほんと「それだけ」であとの設計はClassコンポーネントから、謎ルール満載の複雑なHooks関数コンポーネントも含めて惨憺たる実装です。

ですから、まあこの点に関してだけは本記事にズラッと引用されている英語の批判記事の内容は正しいんでしょう。ろくに見ても居ませんが、Reactがろくでもないくせに過剰評価されていることだけは事実なので内容を読む前から同意できます。

また、思想的にも酷いなとずっと感じているのが、Reactというライブラリ名のくせにドキュメントでReactiveProgrammingについて頑なに説明を拒否しているように見えることです。

SolidJSでもVanJSでも、ReactiveProgrammingというコアの概念についてかなりはっきりと提示されています。

しかし、Reactのドキュメントでは、ReactiveProgramming なんて概念はまるで存在しないが如く周到に迂回して説明しているので、わけがわかりません。

https://ja.react.dev/learn

Reactのドキュメントで初心者が入門するのは非常にハードルが高いと思います。

今から始めるのであれば、わざわざこのライブラリを選択する合理的理由は巷でのシェアが大きい、という理由しかなく、はじめるのならVanJSかSolidJSをオススメします。

HTMXについては、ちょっと要素の編集が入るような初歩的なUI実装のためには、原始的レベルの型チェックもなんも効かないと思われる、長大なJavaScriptの文字列をベタ書きしても良い、また、そのレベルの複雑姓の破綻は、次のレベルでは必ず組合せ爆発が起こる、という事実を見なかったことにする人々向けだと感じます。

オトワオトワ

自分でなっといてアレなんですが、ぼくもHTMXのCEOというのはよくわかってないですね。ジョークサイト的なアレなんだと思いますが。
脚注で書いたとおり、ここからHTMXの話につなげるには、反SPAという思想的な話を通る必要があると思います。
話の主眼はあくまでReactだったんですけれどもね。HTMXだからどうということではなく、SolidJSやRuby等の非JSにおいても、Reactのパフォーマンスの悪さ(や複雑さ)への批判というのは背景としてあるのであって、固有のフレームワークの話をしてるつもりはなかったのですが。
本当にHTMXのCEOになれたのが嬉しくて書いた記事だったのですが、前段に書いたのが誤解を招いたかもしれませんね。

Ken OkabeKen Okabe

別に自分は何も誤解はしていない、と思いますが、Reactがパラダイムチェンジャーであっただけで、その後多くの人が王様は裸であると言えなかったり、そもそも判断能力がなかったりしただけで過剰評価されてきた事実はURLの列挙がされているので、そこだけは価値がありますね。
そして本記事でそれ以外の理由付けとして一貫して語られているバンドルサイズが小さいのでパフォーマンスが良い、仮想DOM云々、というのは全部間違いです。
宣言型リアクティブUIのパラダイムチェンジは正しいので、バンドルサイズだけが正義理論だけでゴリ推ししたいのであればHTMXじゃなくてVanJSのほうが正義ということにもなりますよね。
反SPAという思想的な話であったならば、これもバンドルサイズとは無関係な話なのでそこで別途立論する必要があります。