Gumroadがhtmxを選ばなかった理由

Sahil Lavingia

Gumroadでは最近、Helperという新しいプロジェクトを開始しました。CEOとして、私は当初、このプロジェクトにhtmxを使うことに非常に楽観的でしたが、一部のチームメンバーはそれほど乗り気ではありませんでした。

私の楽観主義は、Reactを使った過去の経験から来ており、Reactはしばしば私たちのニーズに対して過剰だと感じていました。htmxはフロントエンドを非常に軽量に保つための良い解決策になるだろうと考えていました。

Gumroad Red
htmxを使ったソース - 画像をクリックして表示

実際、私はこの考えをSlackでチームと共有しました。

「https://htmx.dokyumento.jp/ は、シンプルなインタラクションを追加するための手段になるかもしれない」

そして、最初は有望に見えました! Gumroadのエンジニアの一人が雄弁に述べたように

「HTMXは(正式に)JSの世界が過度に複雑になっていることを嘲笑するミームです。TailwindがインラインCSSの別の構文であるように、HTMXはインラインJSの別の構文です。」

しかし、私たちのツールキットでその場所を見つけたTailwindとは異なり、htmxは私たちの目的にはスケールせず、少なくとも私たちのユースケースでは、顧客にとって最高のユーザーエクスペリエンスにつながりませんでした。

その理由を以下に説明します。

  1. 直感と開発者体験:htmxで正しいことをすることは可能でしたが、Next.jsを使ってすべてを動作させる方がはるかに直感的で楽しいと感じました。開発プロセスはNext.jsでは自然に感じられましたが、htmxではしばしば不自然で強引に感じました。例えば、動的なバリデーションや条件付きフィールドを含む複雑なフォームを構築する際、Reactでは簡単なクライアントサイドの操作になるものを、処理するために複雑なサーバーサイドのロジックを書くことになりました。

  2. UXの制約:htmxは、私たちのアプリをRails/CRUDアプローチに押し進めることになり、結果として、デフォルトでは非常に貧弱な(少なくとも、退屈で一般的な)ユーザーエクスペリエンスにつながりました。私たちは常にこの傾向と戦っていることに気づき、それは逆効果でした。例えば、ワークフロービルダーにドラッグアンドドロップインターフェースを実装することは、htmxでは大きな課題であり、Reactライブラリで実現できるスムーズなエクスペリエンスと比較して、扱いにくい回避策が必要でした。

  3. AIとツールサポート:AIツールは、オープンソースのトレーニングデータが不足しているため、Next.jsには精通していますが、htmxにはそれほど精通していないことに注意する必要があります。これはRailsが直面している問題と似ています。決定的な要因ではありませんでしたが、開発速度と問題の解決策を見つけることの容易さに影響を与えました。問題に遭遇したとき、React/Next.jsで利用できる豊富なリソースにより、トラブルシューティングがはるかに高速になりました。

  4. スケーラビリティに関する懸念:プロジェクトが複雑になるにつれて、htmxは私たちのニーズに対応するのに苦労していることに気づきました。最初に私たちを魅了したシンプルさは、より高度なインタラクションと状態管理を実装しようとするにつれて、制限的に感じ始めました。例えば、リアルタイムコラボレーションや複雑なデータ視覚化などの機能を追加するにつれて、複数のコンポーネントにわたる状態の管理は、htmxのサーバー中心のアプローチではますます困難になりました。

  5. コミュニティとエコシステム:React/Next.jsのエコシステムは広大で成熟しており、私たちが遭遇したほとんどすべての問題に対するソリューションを提供しています。htmxでは、私たちはしばしば車輪の再発明をしたり、機能を妥協したりすることに気づきました。これは特に、サードパーティのサービスやライブラリを統合する必要がある場合に顕著になり、それらはしばしばReactバインディングを持っていましたが、htmxに相当するものは持っていませんでした。

Gumroad Green
NextJSを使ったソース - 画像をクリックして表示

最終的に、私たちはReact/Next.jsに移行することになり、これは私たちが探していた複雑なUXを構築するのに非常に適していました。私たちは今のところこの決定に満足しています。これにより、より迅速に移動し、より魅力的なユーザーエクスペリエンスを作成し、既存のツールとライブラリの豊富なリソースを活用することができました。

Gumroad Helper Before After
Gumroad Helperのビフォー&アフター - 画像をクリックして表示

この経験は、重要な教訓を再認識させました。軽量な代替案を検討することは重要ですが、プロジェクトとともに成長し、長期的なビジョンをサポートできるテクノロジーを選択することも同様に重要です。Helperにとって、ReactとNext.jsはその選択肢であることが証明されました。

そこに移って以来、私たちはコアな顧客のためにアプリのユーザーエクスペリエンスを大幅にアップグレードすることができました。

  1. ドラッグアンドドロップ機能:ワークフロービルダーの主要な機能の1つは、ドラッグアンドドロップを通じてステップを並べ替える機能です。htmxでドラッグアンドドロップを実装することは可能ですが、利用可能なソリューションは扱いにくく、大幅なカスタムJavaScriptが必要であると感じました。対照的に、Reactエコシステムは、最小限の設定でスムーズでアクセス可能なドラッグアンドドロップを提供するreact-beautiful-dndのようなライブラリを提供しています。

  2. 複雑な状態管理:各ワークフローステップには、独自の構成と条件付きロジックのセットがあります。ユーザーがこれらを編集すると、変更と他のステップへの影響を反映するために、UIをリアルタイムで更新する必要があります。htmxでは、これは多数のサーバーラウンドトリップ、またはhtmxのサーバー中心の哲学に反する複雑なクライアントサイドの状態管理が必要になります。Reactの状態管理ソリューション(useStateやReduxのようなより高度なオプションなど)により、これがはるかに簡単になりました。

  3. 動的なフォーム生成:各ステップタイプの構成は異なり、ユーザー入力に基づいて変更できます。これらの動的なフォームを生成し、その状態を処理することは、Reactのコンポーネントモデルではより直感的でした。htmxでは、これらのフォームを生成および検証するために、より複雑なサーバーサイドのロジックを書くことになりました。

  4. リアルタイムコラボレーション:このスクリーンショットには表示されていませんが、複数のユーザーが同時にワークフローを編集できる機能が実装されています。WebSocketとReactを使用してこれを実装することは比較的簡単でしたが、htmxでは、リアルタイムの更新を処理するために、より複雑なサーバーサイドのロジックとカスタムJavaScriptが必要になります。

  5. パフォーマンスの最適化:ワークフローが大きくなり、複雑になるにつれて、レンダリングの最適化を細かく制御する必要がありました。Reactの仮想DOMとuseMemoやuseCallbackのようなフックにより、htmxではすぐには利用できない、または直感的ではない方法でパフォーマンスを最適化することができました。

これらの課題がhtmxでは乗り越えられないわけではないことは重要ですが、それらに対処することは、しばしばhtmxの強みから離れて、JavaScriptを多用する環境でより自然に感じるソリューションに向かうことになると感じました。この認識は、ReactとNext.jsに切り替えるという私たちの決定の重要な要因でした。

特に単純なインタラクションモデルを持つプロジェクトや、既存のサーバーレンダリングアプリケーションの上に構築されたプロジェクトなど、htmxは多くのプロジェクトに最適である可能性があることを認識しています。私たちの経験は、他の人がhtmxに見出した利点を無効にするものではありません。重要なのは、プロジェクトの特定のニーズを理解し、これらの要件に最も適合するツールを選択することです。

私たちの場合、Helperのインターフェースの複雑で状態を持つ性質により、ReactとNext.jsの方が適していました。ただし、私たちは引き続きhtmxのアプローチを高く評価しており、その強みが私たちのニーズにより適合する将来のプロジェクトで検討する可能性があります。

とは言うものの、私たちはニーズが進化し、新しいテクノロジーが登場するにつれて、常に技術スタックを再評価することにオープンです。未来が何をもたらすかは誰にもわかりません。

</>