htmxとは何なのか？ その背景にある思想について

先日、Qiitaに投稿された一つの記事が注目を集めました。

https://qiita.com/twrcd1227/items/7bce18167fb02ec22729

元記事では、htmxというJavaScriptライブラリが英語圏で認知を獲得しているとして、インストールの仕方から使い方について公式のドキュメントの全体にわたって簡単に説明が行われています。

さまざまなプラットフォームでこの記事に対する反応を観察してみると、どちらかというと懐疑的な見方のほうが優勢のように見受けられます。ただ、多くのコメントは誤解に基づいているように見受けられました。「JSが要らない」といった元記事のミスリードによるところも大きそうですが[^1]、なぜhtmxが大きく支持を得つつあるのかを理解するには、背景情報を含めて理解することが必要です。

[^1]: htmxの作者は明白に「アンチJavaScriptライブラリではない」と[述べています](https://youtu.be/d0LwUqb9e_k?feature=shared&t=675)。

htmxは、最近の複雑化するフロントエンド技術に対する単なる逆張りではありません。**これまで30年ほどのあいだウェブ上のシステムを支え続けた「ハイパーメディア」の持つ強力さに今一度目を向けてみようという提言が含まれている**と私は考えています。

この記事を読むことで、htmxというライブラリがなぜ一部のエンジニアから支持を得ているのか、少しでも伝えられたら幸いです。

## htmxとは何か？

最初に、htmxとはどのようなライブラリなのかをおさらいしてみます。ほぼ公式ドキュメントの“[htmx in a Nutshell](https://htmx.org/docs/#introduction)”からの引用です。

htmxはJavaScriptに頼らず、HTMLを通じてモダンブラウザの機能に直接アクセスすることを可能にするライブラリです。

htmxを理解するために、まずアンカータグを見てみましょう：

```html
<a href="/blog">ブログ</a>
```

このアンカータグはブラウザーに次のように指示します：

> ユーザーがこのリンクをクリックしたら、'/blog'にHTTP GETリクエストを発行し、レスポンスの内容をブラウザーのウィンドウに読み込みます。

これを踏まえて、次のようなHTMLの例を考えてみましょう：

```html
<button hx-post="/clicked"
    hx-trigger="click"
    hx-target="#parent-div"
    hx-swap="outerHTML"
>
    クリックしてください！
</button>
```

これはhtmxに次のように指示します：

> ユーザーがこのボタンをクリックしたら、'/clicked' にHTTP POSTリクエストを発行し、レスポンスの内容を使ってDOM内のid `parent-div` の要素を置き換える。

htmxは、ハイパーテキストとしてのHTMLの核となる考え方を拡張・一般化し、言語内で直接多くの可能性を開きます：

- アンカーやフォームだけでなく、どんな要素でもHTTPリクエストを発行できるようになります
- クリックやフォーム送信だけでなく、どのようなイベントでもリクエストをトリガーできるようになります
- `GET` や `POST` だけでなく、どんな [HTTPメソッド](https://en.wikipedia.org/wiki/HTTP_Verbs) も使えるようになります
- ウィンドウ全体だけでなく、どんな要素もリクエストによる更新の対象にできます

htmxを使用している場合、サーバー側では通常、*JSON*ではなく、*HTML*で応答することがポイントです。

（後略）

## htmxが前提とするアーキテクチャスタイル

コア機能となるものは前節で述べたものがほぼ全てです。レンダリングやステート管理の機構は用意されていません。

誤解を呼ばないよう補足しますが、**htmxはクライアントサイドのスクリプトを否定していません**。htmxの範疇ではないというだけで、htmxのコンパニオンとして同じ開発元が公開している[hyperscript](https://hyperscript.org/)や、[Alpine.js](https://alpinejs.dev/)などのライブラリを使うことで簡単にクライアントサイドに振る舞いを与えられます。もちろんそれ以外のUIライブラリや、Reactすらも併用可能です。

htmxの世界観において、HTMLはサーバーサイドでレンダリングされます。アプリケーション状態の変更のためにサーバーにリクエストを行い、状態変化をサーバーサイドから受け取ります。JSONのやりとりはなく、常にHTML表現を受け取ります。

現在のフロントエンド開発シーンに馴染んでいると、一見パラダイムの退化的アプローチなようにも思えます。ですがhtmxが飽くまでそこに留まるのは、**旧来からのアーキテクチャスタイルが持つシンプルさと柔軟性が過小評価されていると考えているから**です。

この旧来からのアーキテクチャスタイルとは、よく知られているRESTの概念に他なりません。この記事ではRESTに関する一般的な誤解[^2]には触れませんが、RESTの制約のうちの一つであるハイパーメディア制約＝**HATEOASに再びスポットライトを当てようとしている**のがhtmxなのです。

[^2]: RESTやHATEOASってAPIのものでは？　と思われたあなたはRESTを誤解している可能性があります。[htmx作者によるエッセイ](https://htmx.org/essays/)をお薦めします。

## HATEOASの再評価

HATEOAS（Hypermedia as the Engine of Application State）では、クライアントは、サーバーから送られてくるハイパーメディア表現を通じてアプリケーションと対話します。サーバーとの対話方法はレスポンスのハイパーメディアの中に記述されているため、**クライアントはそれ以上の予備知識を必要としません**。これは今日のJSONベースのウェブクライアント（＝データの消費方法やサーバーとの対話方法を別途知る必要がある）とは対照的です。

具体的に言うと、ここでいうハイパーメディアとは、言うまでもなくHTMLです。サーバーは、画面遷移のための`<a>`要素やデータ更新のための`<form>`要素といった「ハイパーメディアコントロール」を通じて、アプリケーション状態を変更するエンドポイントとパラメーター構築の方法をクライアントに伝えます。クライアントはロジックを持つ必要は無く、ごく薄く保つことができます。

HATEOASはまったく新しいものではありません。このモデルはウェブの黎明期からウェブアプリケーションを支えてきた、信頼と実績のある考え方です。HATEOASだったからこそ、ウェブベースのアプリケーションがここまで成功を収めてきたといっても過言ではないでしょう。

しかし、HTMLはハイパーメディアシステムのための言語としては進化を止めてしまいました。`<form>`要素が使えるHTTPメソッドはGETとPOSTだけです。リクエストに任意のHTTPヘッダーを含めることはできません。ページ遷移は常に全画面が切り替わり、スタイルやスクリプトの評価はそのたびに実行されてしまい、効率が良くありません。

htmxの作者Carson Gross氏は、HTMLをより強力なハイパーメディアにしたらどうなるか？　と考え、htmxを開発しました。そして、HATEOASを使ったマルチページアプリケーション（MPA）のシンプルさおよび柔軟性と、シングルページアプリケーション（SPA）の応答性の高さを両立させたHDA = Hypermedia Driven Applicationという概念を提唱しました。

> The HDA architecture achieves this goal by extending the existing HTML infrastructure of the web to allow hypermedia developers to create more powerful hypermedia-driven interactions.
> 
> HDAアーキテクチャは、ウェブの既存のHTMLインフラストラクチャを拡張し、ハイパーメディア開発者がより強力なハイパーメディア主導のインタラクションを作成できるようにすることで、この目標を達成する。
> 
> ― [Hypermedia-Driven Applications](https://htmx.org/essays/hypermedia-driven-applications/)

着想について理解すると、「どんな要素でもHTTPリクエストを発行できる」や「どんな要素もリクエストによる更新の対象にできる」といったhtmxの方向性にも一定の理解ができるのではないでしょうか。

## htmxを採用する利点

HDAアーキテクチャを採用すると次のようなメリットが得られると考えられます。

- **アーキテクチャ上の複雑性を劇的に減らせる。**
    クライアントはデータの型について知る必要がなく、条件分岐やバリデーションといった複雑なロジックも不要です。サーバーから送られてくるハイパーメディアをレンダリングするだけでほぼ完結します。クライアントは薄くシンプルになります。BFFなど追加の層も必要ありません。

- **画面遷移を伴わないインタラクティブなアプリケーションを構築できる。**
    SPAフレームワークが採用される動機の一つである状態遷移のスムーズさは、SPAほど洗練されていないにせよ、十分なレベルで実現できます。

- **バックエンド技術に何を選んでもよい。**
    PythonでもRubyでもPHPでも、なんでも好きなバックエンド技術を採用できます。

- **データへのフルアクセス権限が得られる。**
    当たり前と言えば当たり前ですが、サーバーサイドがアクセスできるデータには自由にアクセスできます。秘匿データがうっかりソースコードに含まれてしまうような心配もありません。

## htmxに向かないプロダクト

どのような技術にも向き不向きがあり、htmxも例外ではありません。

htmxは例えばブラウザーで動くスプレッドシートのアプリには明らかに向きません。通信を伴う高度なインタラクションを要求するようなものにも合わない可能性が高いです。

ですが、**世の中の大半のウェブベースのシステムやアプリケーションにおいて、htmxは十分現実的な選択肢になり得ます**。実際のところ、それほど高度なインタラクションが必要なアプリケーションは多くないからです。

部分的に多くのインタラクションが必要になったとしても、「アイランド的にSPAを適用する」アプローチがまだ残されています。

また、「htmxを使ってどれほど遠くまで行けるのか」もまた興味深い観点です。これは、基軸になるMPAのアプローチがどこまでスケールするのかを考えるのと同義でしょう。「どこまででも行ける」と言っていいと考えます。

## 複雑性を回避する

モダンなアプローチを避けようとする理由は、複雑性の高さがキーワードになるでしょう。htmxの作者は、“[The Grug Brained Developer](https://grugbrain.dev/)”というエッセイで複雑性に対する強い気持ちを表明しています。

> complexity _very_, _very_ bad
> 
> 複雑性マジほんとよくない

他にも、Svelteの作者でありフロントエンドのオピニオンリーダーであるRich Harris氏に対し“[A Response To "Have Single-Page Apps Ruined the Web?"](https://htmx.org/essays/a-response-to-rich-harris/)”というエッセイにおいて複雑性を引き合いに出して反論が試みられています。

> For many of us, however, the javascript ecosystem is simply _insanely_ overly-complicated. Comically so, in fact, given the requirements of most web applications.
> 
> しかし、私たちの多くにとって、javascriptのエコシステムは単にめちゃくちゃ複雑だ。実際に、ほとんどのウェブアプリケーションの要件を考えると、それはもう滑稽なほどだ。

このように、htmxの作者は、徹底的に複雑性を回避する志向性を持っている人物と言えそうです。

一方で、努力なくして複雑性を回避することはできません。この点について、htmxの作者はいくつか示唆深いエッセイを書いています。

まず“[10 Tips For Building SSR/HDA applications](https://htmx.org/essays/10-tips-for-ssr-hda-apps/)”より：

> Accepting a slightly less efficient and interactive solution to a particular UX can save you a tremendous amount of [complexity](https://htmx.org/essays/complexity-budget/) when building a web application.
> 
> 特定のUXに対して、少し効率性とインタラクティブ性を犠牲にした解決策を受け入れることは、ウェブアプリケーションを構築するときに、膨大な量の複雑さを節約することができる。

SPAアプローチによる洗練されたUXを提供できる可能性は認めた上で、少しだけその度合いを犠牲にすることで、複雑性を大幅に削減できると言っています。

次に、“[The Grug Brained Developer](https://grugbrain.dev/)”より：

> best weapon against complexity spirit demon is magic word: "no"
> 
> 複雑さの悪魔に対抗する最高の武器は、魔法の言葉「ノー」だ。

同じく“The Grug Brained Developer”より：

> then grug spend time think of [80/20 solution](https://en.wikipedia.org/wiki/Pareto_principle) to problem and build that instead.  
> 80/20 solution say "80 want with 20 code" solution maybe not have all bell-whistle that project manager want, maybe a little ugly, but work and deliver most value, and keep demon complexity spirit at bay for most part to extent
> 
> sometimes probably best just not tell project manager and do it 80/20 way. easier forgive than permission,
> 
> そして、グラッグ［訳注：著者自身のこと］は時間をかけて[80/20の解決策](https://en.wikipedia.org/wiki/Pareto_principle)を考え、代わりにそれを作る。 
> 80/20の解決策とは、「20のコードで80の要望を実現する」解決策である。プロジェクトマネジャーが望むお飾りの機能は持っていないかもしれないし、少々醜いかもしれないが、機能し、最も価値のあるものを提供し、悪魔のような複雑さを抑えることができる。
> 
> 時には、プロジェクトマネジャーに黙って、80/20のやり方でやるのがベストかもしれない。許可するよりも、許す方が簡単だ。

要求される全ての要求にイエスと答えるのではなく、過剰な複雑性を持ち込む要求にはしっかりとノーと伝えていくことが重要だと述べます。また、100%の要求を実現するのは多大な努力が必要なことがありますが、80%の要求になら簡単に応えられるなら、そちらを選ぶほうが良いと考えているのです。

htmxは、要求仕様をすべて実現することを目標としておらず、80の要求をより素早く達成することに主眼を置いて開発されているライブラリなのだと考えられます。

## もっと知るには

htmxとMPAで作ってみるのが一番手っ取り早いでしょう。また、類似のアプローチを取る他のプロダクトに触れてみるのもいいかもしれません。

https://turbo.hotwired.dev/

HotwireのTurboはhtmxと同様のライブラリです。iframeを思わせる概念を用いてアーキテクチャを洗練させているので、Turboの方がしっくり来る人もいるでしょう。

https://unpoly.com/

Unpoly.jsはダイアログ展開やフォーム検証など、実際のユースケース別の機能も盛り込まれているライブラリのようです。
	
ハイパーメディアドリブンのアプローチについてもっと掘り下げて学んでみたい人は、htmxの作者による書籍 **“[Hypermedia Systems](https://hypermedia.systems/)”を読んでみることを強くお薦めします**。

オンラインにて無料で読めます。この書籍の想定読者層は、Vue.jsやReactのようなSPAアプローチのアプリケーション開発しか経験のないエンジニアなので、すんなりと読み進められるでしょう。ベテランエンジニアであっても、HDAの持つ強力さを改めて思い出させてくれると思います。

<ins datatime="2025-05-23">2025年5月23日 追記：縁があり、本書の日本語訳をがけることになりました。6月11日に日本語版『[ハイパーメディアシステム](https://gihyo.jp/book/2025/978-4-297-14945-1)』が技術評論社から出版されます。何とぞよろしくお願いします。</ins>

https://gihyo.jp/book/2025/978-4-297-14945-1