世界を動かす技術を、日本語で。

メッシュ: Htmxを試してみたが、やめた

概要

Web開発界隈 で「JavaScript Fatigue」や「HTML Over The Wire」などの議論が活発化。 HTMX が注目され、HTML属性による宣言的な開発手法が再評価。 SPAフレームワークの構造性とHTMXの柔軟性のギャップが課題。 MESH は「1コンポーネント=1エンドポイント」という新しいSSRアプローチを提案。 Shadow DOMとHTMXの連携、OOBアップデートなど最新技術の実装例を紹介。

Web開発の潮流とHTMXの台頭

  • Web開発者 の間で「JavaScript Fatigue」「Framework Fatigue」などの言葉が話題
  • HTML Over The WireHypermedia Revival など、HTMLファーストな開発手法の再評価
  • HTMX がこの流れの象徴的存在、HTML属性で多くの操作を実現
  • ブラウザがHTMXのようなセマンティクスを ネイティブサポート すれば、JavaScript不要なWeb実現も可能性
  • 従来のSPA は構造性や規約で人気だが、HTMXは柔軟すぎてスパゲッティ化の懸念

HTMXの課題とMESHの発想

  • HTMX は開発者に構造や規約を委ねるため、設計の一貫性確保が難題
  • 宣言的jQuery」との印象を持つ開発者も多い
  • SPAフレームワーク のような「唯一正しい方法」がほしいというニーズ
  • MESH は「1コンポーネント=1エンドポイント」を原則としたSSRフレームワーク
  • HTMLファーストな開発体験と SPA的な構造性 の両立を目指す

基本的なインタラクションと技術スタック

  • HTMXDeclarative Shadow DOM(DSD) の組み合わせが有望視
  • Go+Templ をバックエンドに採用、爆速ビルド&デプロイ体験
  • Junie による「vibe coding」も試行
  • HTMX はShadow Rootを越えられない制約あり、JSフックで回避策を実装
    • htmx:beforeSwapイベントでShadowRootごとにスワップ制御

MESH流コンポーネント設計例

  • mesh-card カスタム要素:HTML, CSS, JS, バックエンドコードが一体
    • <template shadowrootmode="open">でShadow DOMを宣言
    • HTMXと連携しつつ、JSでインタラクション追加
  • MeshElement ベースクラス:ShadowRootのセットアップとHTMX処理
    • イベントリスナーの自動バインド
    • HTML属性でメソッド名を指定し、JS関数へ接続
  • Cardクラス :表示切り替えや編集機能をJSで実装
    • edit()cancel()などのメソッドでUI制御

親子間連携とOOBアップデート

  • HTMX で親コンポーネントの状態更新が課題
    • 「ターゲット拡張」や「レスポンスヘッダーイベント」など複数の流派
    • OOB(out of band)スワップ が最新のベストプラクティス
      • サーバーレスポンスに他のコンポーネントも含めて返却、HTMXが自動で差し替え
  • MESH ではOOB更新用のPub/Subを実装
    • イベントごとにコンテキスト付きでコンポーネントを描画
    • 親子の依存なしで独立した更新が可能

Shadow DOMとHTMXの壁・解決策

  • HTMX はShadowRootを越えてDOM操作できない仕様
  • Shadow DOMとの共存には追加ハックが必要
    • findInShadow関数でShadowRootを再帰的に探索し、IDで要素を特定

まとめ:HTMLファースト×構造的なWeb開発への提案

  • MESH はHTMXの柔軟性とSPA的な構造性を両立する新アプローチ
  • Shadow DOMOOBアップデート など、現代的Web技術の課題と解決策
  • 今後のWeb開発は「HTMLファースト」「唯一の正しい方法」「構造性と柔軟性のバランス」が鍵
  • MESH の詳細やコードは GitHub で公開中、実践例も豊富

参考

  • HTMX公式サイト
  • MESH GitHubリポジトリ
  • Go + Templドキュメント
  • Declarative Shadow DOM仕様書

Hackerたちの意見

今、私が注目しているのはC#のBlazorだね。もう8年くらい経ってるかな?基本的には、C#を使ってフロントエンドのバックエンドダイナミックレンダリングをやる(サーバーBlazor)か、Web Assemblyにコンパイルするかのどちらかだよ。もう1年以上JSを書いてないし、UIもRazorページの作り方に似てる。これは多くのウェブフレームワークがBlazorのような技術に投資すれば、ウェブ開発の未来だと思ってる。PhoenixのLiveViewも思い浮かぶね。誰か勇気ある人がDjango用にBlazorに似たものを作ってくれることを期待してる(試してみたいと思ってるけど、今はサイドプロジェクトが多すぎて手が回らない)。

BlazorはSilverlightのように消えると思う。HTML、CSS、JavaScriptを学べばいいよ。

Blazorを試してみたけど、自分のニーズには複雑すぎて重すぎた。Phoenix/LiveViewの方が成功したよ。

なんで誰がRazorの構文を使うことを選ぶのか、全く理解できない。ウェブのために使うなんて尚更。そんなに複雑にする必要はないよ、HTMLは解釈されるんだから。記事にもあるように: > HTMXは開発者に自分のコードに規律を課すかどうかを任せているけど、それが悪いことのように言われてる。Angularみたいなフレームワークが「Angularのやり方でやらなきゃダメ」って言うのが本当に嫌いだ。そういうのは革新や小さな問題を解決するアイデアを遅らせるだけだよ。もし遅いフレームワークがあったら(最近のCloudflareの一部の人たちのReact実装を見てると)、たぶんそれを考慮しないか、単にフレームワークの「特異性」として見るだけだろうね。

確かに - すごく興味深いのは、これらのフレームワークが引き寄せられる「アトラクター」が明らかに存在することだね。これがブログ記事で伝えたかったことの主な部分なんだ。MESHは全くの解決策じゃなくて、なぜそうなるのかを示すために作ったものだから、LiveViewやBlazorと同じようにね。私の疑問は、これがHTML仕様に戻って統合され、ブラウザにサポートされる形があるのかどうか。直感的にはないと思うけど。

BlazorとPhoenixは、特にビジネスロジックがたくさん必要な複雑なフロントエンドを構築する時に、私にとっても直感的だね。そういう作業でJSを使わなくて済むのは素晴らしい。

Blazorでいくつかおもちゃを作ったんだけど、今はJavaの会社でVaadinを使ってるチームがあるよ。実装はちょっと違うけど、バックエンドの言語を使ってフロントエンドのコードを書くっていうアイデアは似てるね。

ある会社では、契約者が来て「簡単なIoTダッシュボードをボタンいくつかで作れるよ、Blazor使いたい」って言ってたんだ。俺はPhoenix LiveViewを使って、rpi3やその後のrpi4でも問題なく動いてたから、Blazorも大丈夫だろうと思ったんだけど、結局Blazorは4GBのRAMを積んだRPiを完全にダメにしちゃったんだ。ページが読み込まれるのに数分かかったしね。もちろん、それは数年前の話だけど。今はBlazorが改善されてることを願ってる。あの時点から考えると、Elixir LiveViewの効率には到底及ばないと思う。個人的には、他のシステムがElixirのLiveViewを再現するのは難しいと思う。BEAMの設計が先行型アクターを使ってるからね。可能ではあるけど、応答性やリソースの使い方を合わせるにはかなりの労力が必要だと思う。今はNimをバックエンドとフロントエンドで使ってて、Karax SPAを使ってるんだ。同じコードをフロントエンドとバックエンドで共有できるのはすごくいいよ!

前の仕事ではBlazorから離れようとしてたんだ(ちょっと残念だった、俺はその哲学が好きだから)。なぜなら、デプロイするたびにセッションが壊れて、全てのアクティブユーザーが切断されちゃったから。

これはWebFormsやGWT、JSFのやり方に戻るようなもので、実装は2000年代とはちょっと違うけどね。生成されたものをデバッグするのが大変だったから、MVCアプローチに移行したんだ。ブラウザが実際にサポートしている技術から生成されるものをデバッグするのが本当に面倒だったから。Blazorには明るい未来は見えないな、学びたくない.NETの会社がいくつかあるだけで。

私はこれがウェブ開発の未来だと思っている まあ、C#ではないけどね。RustはWASMにコンパイルするにはずっと良い言語だ。LeptosはBlazorと似たようなことを、CPUとバイトのほんの一部で実現している。 https://leptos.dev/ Blazorは、最悪のJSソリューションよりもクライアントサイドでずっと遅い。右にスクロールすると比較が見れるよ: https://krausest.github.io/js-framework-benchmark/current.ht... C#でウェブスタックを全部扱えたらいいんだけど、残念ながらWASMバンドルはほとんどのユースケースには重すぎる。それに、フロントエンドのDXも、10年前のJSとWebpackの時代ほど良くないし。最近はViteでハードルがずっと高くなってる。

この小さなヘルパーのおかげで、コンセプトを証明するためのシンプルなTrelloクローンを作り始められる。htmxを使う前にhypermedia.systemsを読む価値があるかも。書籍自体も、よりインタラクティブなコンポーネントにはJavaScriptや好きなインタラクティブフレームワークを使うべきだと言ってる。Djangoでhtmxを使うのは、 - 今後数年で依存関係を最小限にアップグレードする確信が持てるとき - 何か標準的なこと(ダッシュボード/管理UI)をやっているときだね。

この投稿には複雑な気持ちだ。一方では、励ましや明るさがある。もう一方では、HTMXを評価するふりをして、HTMXとは関係ない規約を強調している。ネタバレ: HTMXは人工的な制約の下では機能しない。

このアプリはhtmxには合わなかったみたいだね。htmxのウェブサイトの「On The Other Hand」セクションに追加したよ: https://htmx.org/essays/#on-the-other-hand 「innerHTML」のデフォルトのスワップ動作についてはここで確認できるよ: https://htmx.org/quirks/#the-default-swap-strategy-is-innerh... htmxの機能をHTML仕様に統合する提案ではouterHTMLを使ってる: https://alexanderpetros.com/triptych/ datastarも考慮してみて、これはSSEファーストの視点からGoエンジニアが書いたものだよ: https://data-star.dev/

あなたみたいな人がもっといたらいいのに <3

わあ!これはすごい名誉だ、ありがとう!「lol HTMXはクソだ」って投稿を書こうと思ったけど、正直じゃなかった。HTMXは信じられないほど強力で、みんながやってることにファンなんだ。このサーバーサイドレンダリングの何かを書く試みは、HTMXが俺に(そしてみんなに)与えてくれる刺激がなければ実現しなかったよ。

うん、俺の(限られた)経験では、htmxはオールドスクールのマルチページアプリの車輪を潤滑するのに最適だと思う。htmxを使ってSPAっぽいドラッグ&ドロップのインタラクティビティを作ろうとしたけど、最終的な結論は、そういう機能は一つの大きなhtmxスワップユニットとして完全にカプセル化するか、htmxの外でjsの「アイランド」として書くべきだってことだった。

あなたの正直さと現実主義には新鮮さを感じる。htmxやDatastarのようなプロジェクトの第一原則思考は、ウェブ開発には非常に必要だ。フィールドは、もともとデザインが悪かったトレンドを盲目的に追いかけることで、長い間道を外れてしまっている。

datastarに+1。HTMXがちょっと遅すぎるところで、すごくバカなプッシュベースのストリーミングHTMLができるよ(マルチプレイヤーアプリに最適)。[1] triptychにもすごくワクワクしてる!それを推進してくれてありがとう。 - [1] https://checkboxes.andersmurphy.com

このアプリはhtmxには合わなかったみたい 逆に考えてみると、htmxがそのアプリには合わなかったってことかもしれないね。

https://github.com/cookiengineer/gooey

ちょっとバカな質問だけど、なんでHTMXのデフォルトがinnerHTMLなのに、仕様のマージではouterHTMLなの?

こういうアプリってHTMXには合わないと思う?ドラッグ&ドロップのインタラクティビティとか。

HTMXを使って実験してる人がいるのはいいね、ぜひ続けてほしい。でも、MESHは自分のプロジェクトには選ばないかな。 - 複雑なアプリには、JSXのように複雑さをシンプルで明確なコンポーネントに分解できるところが好き。 - シンプルなアプリには、HTMXが生のHTMLとAPIレスポンスの関係を明確にする能力が好き。MESHの例を見てると、JSXのシンプルさやHTMXの透明性を達成してない冗長なコードが多い気がする。それでも、まだMESHを理解してないから、プロジェクトで使ったら何かひらめくかもしれない。

これには最後に「まとめ」みたいなものがあったらもう少し良かったかな。彼がどこにたどり着いたのかを要約する感じで。MESHページのREADMEはいいまとめになってるよ: > MESHはHTMXの概念を示すことを目的とした楽しいプロジェクトで、HTMXを使わずに実現してるんだ。具体的には、サーバー上でモジュラー要素をレンダリングし、クライアントでそれらをハイドレートして、必要に応じて全ページをリロードするのではなく、入れ替えてる。コンポーネントの更新はその場で入れ替えられる。アウトオブバンドの更新はSSE(サーバーサイドイベント)を通じて全ての接続されたクライアントに送信されるから、全ユーザーがリアルタイムで更新を見られるんだ。(HTMXのアウトオブバンド更新に慣れてない人のために説明すると、MESHではクライアント側でSSEを通じてサーバーから送られる更新をリッスンする何かを接続するんだ。サーバーが送るのは基本的にIDを持ったHTMLのスニペットで、クライアントのリスナーがそのIDを持つDOM内のHTMLを送られたHTMLに置き換える。これにより、サーバーがクライアントのUIを自由に更新できるようになるんだ。)だから、個々の要素を置き換える能力を持ったSSRを行うHTMXのメカニズムの一つを共有してるんだ。

MESHの概念は、粗い粒度のコンポーネントとサーバーアイランドの間に位置してるね。Reactは細かい粒度のコンポーネント用で、HTMXは軽量なインタラクティビティ用 — ページの一部を更新するためのもの。クラシックなReactのユースケースは、編集可能でフィルタブルなドロップダウン。クラシックなHTMXのユースケースは、ボタンをクリックしてテキストを読み込むこと。重なり合う部分は、中間にあって、シンプルなフォームバリデーション。Reactは各フィールドをコンポーネントにして、それぞれのバリデーションとエラーメッセージを処理させると言ってる。HTMXは、エラーメッセージを持った再描画されたフォームを返すだけでいいって言ってる。MESHは、フォームを独自のエンドポイントを持つコンポーネントにしようって提案してるんだ。

もう一つのコメントだけど、htmxの一般的な概念(HTMLの一般化されたハイパーメディアコントロール)に関する異なる動作やデフォルトを試したいなら、89行のコードのfixi.jsをフォークしてみて。デフォルトのスワップ戦略としてouterHTMLを使ってるよ: https://github.com/bigskysoftware/fixi/blob/master/fixi.js これはミニマリズムの実験として作ったんだ: https://github.com/bigskysoftware/fixi#-fixijs---it-aint-muc...

「フレームワーク疲れ」から「新しいフレームワーク」へ、五段落で。個人的には、こういうミニマリストで基本に立ち返るフレームワークはちょっと的外れだと思う。なんか「俺のゲップは臭くない」みたいな感じがする。他の開発者のフレームワークは肥大化してて、依存関係が多すぎて、複雑すぎる。俺の新しいフレームワークはシンプルで、強力なアイデアに基づいてて、ちょうどいいと思う。2025年に本当に良いウェブアプリを作るには、サーバーサイドレンダリングとクライアントサイドレンダリングの両方を取り入れて、クライアントとサーバーで同じレンダリングロジックを共有するのがベストだと思う。例えば、SvelteKitやNext.jsみたいにね。

Next.jsを使うのはマルプラクティスだ。ウェブフレームワークでこんなひどい経験はしたことがない(ここではその言葉をかなり緩く使ってるけど)。

お気に入りのSSRフレームワークはReactに組み込まれてるんだ。renderToStringって呼ばれてる。

MESHはシンプルな原則に基づいている:1つのコンポーネント = 1つのエンドポイント。これは強力なアイデアで、HTMLファーストなバックエンドを書くと、まるでSPAを作っているかのように感じられる。正直言って、HTMXの盛り上がりがまだ完全には理解できていないけど、コアなアイデアの一つは、明らかにSPAを書くようには感じさせないべきだってことだと思ってた。むしろ、昔のPHPやASPスクリプトのように感じるべきなんじゃないかな。つまり、フロントエンドがバックエンドに駆動されるってことだよね。これって、両方の悪いところを合わせ持つことにならない?SPAのモデリングオーバーヘッド + HTMXの密結合?

そういえば、Webコンポーネントで痛い目にあった人たちを思い出すな。彼らはReactコンポーネントと同じ粒度で使ってるから。

正直言って、HTMXの盛り上がりがまだ完全には理解できていない いいタイミングで出てきたよね。ウェブ開発のアイドル、Reactは巨大で扱いにくくて複雑になっちゃった。新しいものたちは、エコシステムの利点でそれを覆すことができなかった。そして、HTMXが独特なマーケティングで全ての正しい音を奏でて、実際に良いアイデアも持ってるって感じで登場した。

MESHはシンプルな原則に基づいている:1つのコンポーネント = 1つのエンドポイント。これは強力なアイデアで、HTMLファーストなバックエンドを書くと、まるでSPAを作っているかのように感じられる。うん、すぐにこのアイデアとHTMXが衝突してるのが分かったよ。HTMXが輝く世界観では、すべてのページはただのドキュメントなんだ。HTMXは、より良いインタラクティビティのための機能を追加するための小さなライブラリに過ぎない。目標は、まさに著者が望んでいたことを避けることなんだ。

MESHでエラーをどう扱うの?HTMXでエラーを処理するには、[0]の設定を使ってレスポンスをエラーダイアログに切り替えたり、hx-on-htmx-send-error [1]やhx-on-htmx-response-error [2]を使ってダイアログを表示するのが好きだよ。いくつかのコンポーネントでは、on-htmx-error属性ハンドラーも使ってる: // https://htmx.org/events/ document.body.addEventListener('htmx:error', function (event: any) { const elt = event.detail.elt as HTMLElement const handlerString = elt.getAttribute('on-htmx-error') console.log('htmx:error evt.detail.elt.id=' + elt.getAttribute('id') + ' handler=' + handlerString) if (handlerString) { eval(handlerString) } }); これでネットワークやサーバーエラーのUXがすごく良くなるよ。[0]: https://htmx.org/quirks/#by-default-4xx-5xx-responses-do-not... [1]: https://htmx.org/events/#htmx:sendError [2]: https://htmx.org/events/#htmx:responseError