はじめに
正直なところ、最近のフロントエンド開発は複雑すぎると思いませんか。
React、Vue、Angular...どれを選んでも、ビルド設定、状態管理、ルーティングと覚えることが山ほどある。30代になって思うのは、シンプルに動くものが一番だということ。
そんな「JavaScriptフレームワーク疲れ」を感じている人に朗報です。htmxというライブラリを使えば、HTML属性を書くだけでモダンなWebアプリが作れます。
htmxはGitHubで46,700スター以上を獲得している、いま注目のライブラリ。「HTMLを完成させる」という哲学のもと、JavaScriptをほとんど書かずにAJAX通信やリアルタイム更新を実現できます。
これ、意外と革命的なんですよ。
htmxとは
htmxは、HTML属性を通じてAJAX、WebSocket、Server Sent Eventsに直接アクセスできる軽量ライブラリです。バージョン2.0.8(2025年12月時点)がリリースされており、444人のコントリビューターによって活発に開発されています。
最大の特徴はJavaScript不要という点。HTMLの属性を追加するだけで、従来はJavaScriptで書いていた動的な処理が実現できます。
<button hx-post="/clicked" hx-swap="outerHTML">
Click Me
</button>
これだけで、ボタンをクリックしたときにサーバーにPOSTリクエストを送り、レスポンスでボタン自体を置き換えることができます。jQueryすら不要です。
公式サイト: https://htmx.org GitHub: https://github.com/bigskysoftware/htmx
特徴・メリット
1. 圧倒的な軽量さ
htmxは**約18kB(gzip圧縮時)**という軽さです。依存関係ゼロで、CDNから読み込むだけで使えます。
React + ReactDOM: 約45kB (gzip)
Vue 3: 約34kB (gzip)
htmx: 約18kB (gzip)
ReactやVueと比べて半分以下のサイズ。コスパ的にかなり優秀ですね。
2. 学習コストの低さ
新しいプログラミング言語や複雑なAPIを覚える必要がありません。HTMLを書ける人なら、すぐに使い始められます。
従来のJavaScriptで書くと:
document.getElementById('btn').addEventListener('click', async () => {
const response = await fetch('/api/data', { method: 'POST' });
const html = await response.text();
document.getElementById('result').innerHTML = html;
});
htmxなら:
<button hx-post="/api/data" hx-target="#result">
データを取得
</button>
<div id="result"></div>
個人的には、このシンプルさがたまらない。
3. HTMLの制約からの解放
従来のHTMLでは、HTTPリクエストを発行できるのは<a>タグと<form>タグだけでした。htmxはこの制約を取り払います。
- どんな要素からでもリクエスト可能
- GET/POST以外のHTTPメソッドも使える
- 任意のイベントでリクエストをトリガーできる
- レスポンスを任意の場所に挿入できる
「ハイパーテキストとしてのHTMLを完成させる」という設計哲学は、なかなか筋が通っています。
4. サーバーサイド言語を選ばない
htmxはサーバーからHTMLを返すだけでOK。Python、Ruby、PHP、Go、Node.js、何でも使えます。
SPAのようにJSONを返してフロントで組み立てる必要がない。これはバックエンドエンジニアにとって非常にありがたい。
5. 67%のコード削減実績
htmxの公式サイトによると、ReactからhtmxへのリプレイスでJavaScriptのコード量を67%削減した実例があるとのこと。
コードが減れば、バグも減る。メンテナンスも楽になる。QOL上がりますね。
インストール方法
CDNから読み込む(推奨)
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"></script>
これだけです。ビルド設定もバンドラーも不要。時短になりますね。
npmでインストール
npm install htmx.org
import 'htmx.org';
unpkgから読み込む
<script src="https://unpkg.com/htmx.org@2.0.8"></script>
正直なところ、CDNから読み込むのが一番手軽でおすすめです。
基本的な使い方
主要な属性
htmxの核となる属性を紹介します。
hx-get / hx-post / hx-put / hx-patch / hx-delete
HTTPリクエストを発行する属性です。
<!-- GETリクエスト -->
<button hx-get="/api/users">ユーザー一覧を取得</button>
<!-- POSTリクエスト -->
<button hx-post="/api/users" hx-vals='{"name": "田中"}'>ユーザーを作成</button>
<!-- DELETEリクエスト -->
<button hx-delete="/api/users/1">ユーザーを削除</button>
hx-target
レスポンスを挿入する場所を指定します。
<button hx-get="/api/data" hx-target="#result">
データを取得
</button>
<div id="result">ここにデータが表示される</div>
CSSセレクタで指定できるので、柔軟性が高い。
hx-swap
レスポンスの挿入方法を指定します。
<!-- 要素の中身を置き換え(デフォルト) -->
<div hx-get="/data" hx-swap="innerHTML">...</div>
<!-- 要素全体を置き換え -->
<div hx-get="/data" hx-swap="outerHTML">...</div>
<!-- 要素の先頭に追加 -->
<div hx-get="/data" hx-swap="beforebegin">...</div>
<!-- 要素の末尾に追加 -->
<div hx-get="/data" hx-swap="beforeend">...</div>
<!-- 要素を削除 -->
<button hx-delete="/item/1" hx-swap="delete">削除</button>
hx-trigger
リクエストのトリガーとなるイベントを指定します。
<!-- クリック時(デフォルト) -->
<button hx-get="/data" hx-trigger="click">クリック</button>
<!-- マウスオーバー時 -->
<div hx-get="/preview" hx-trigger="mouseenter">プレビュー</div>
<!-- 入力後500ms経過時 -->
<input hx-get="/search" hx-trigger="keyup changed delay:500ms" name="q">
<!-- ページ読み込み時 -->
<div hx-get="/initial-data" hx-trigger="load">読み込み中...</div>
<!-- 画面に表示されたとき -->
<div hx-get="/lazy-content" hx-trigger="revealed">遅延読み込み</div>
フォームの送信
<form hx-post="/api/contact" hx-target="#message">
<input type="text" name="name" placeholder="お名前">
<input type="email" name="email" placeholder="メールアドレス">
<textarea name="message" placeholder="メッセージ"></textarea>
<button type="submit">送信</button>
</form>
<div id="message"></div>
バリデーションエラーも、サーバーからHTMLを返せばそのまま表示できます。
インジケーターの表示
<button hx-get="/slow-api" hx-indicator="#spinner">
データを取得
</button>
<span id="spinner" class="htmx-indicator">読み込み中...</span>
.htmx-indicator {
display: none;
}
.htmx-request .htmx-indicator {
display: inline;
}
リクエスト中だけインジケーターを表示できます。これも属性だけで実現できるのが良い。
実践的なユースケース
1. 無限スクロール
<div id="posts">
<!-- 投稿一覧 -->
<div class="post">投稿1</div>
<div class="post">投稿2</div>
<!-- 最後の要素が表示されたら次のページを読み込む -->
<div hx-get="/posts?page=2"
hx-trigger="revealed"
hx-swap="afterend"
hx-indicator="#loading">
</div>
</div>
<div id="loading" class="htmx-indicator">読み込み中...</div>
サーバー側は次の投稿とともに、さらに次を読み込むためのトリガー要素を返せばOK。
2. ライブ検索
<input type="text"
name="q"
hx-get="/search"
hx-trigger="keyup changed delay:300ms"
hx-target="#search-results"
placeholder="検索...">
<div id="search-results"></div>
入力後300ms待ってからリクエストを送信。無駄なリクエストを抑えつつ、リアルタイムに検索結果を表示できます。
3. 削除確認
<button hx-delete="/api/posts/1"
hx-confirm="本当に削除しますか?"
hx-target="closest article"
hx-swap="outerHTML">
削除
</button>
hx-confirmで確認ダイアログを表示。削除後は親の<article>要素ごと消えます。
4. タブ切り替え
<div class="tabs">
<button hx-get="/tab/1" hx-target="#tab-content" class="active">タブ1</button>
<button hx-get="/tab/2" hx-target="#tab-content">タブ2</button>
<button hx-get="/tab/3" hx-target="#tab-content">タブ3</button>
</div>
<div id="tab-content">
<!-- タブの内容 -->
</div>
JavaScriptで状態管理する必要なし。シンプルです。
5. WebSocketでリアルタイム更新
<div hx-ext="ws" ws-connect="/chat">
<div id="messages"></div>
<form ws-send>
<input name="message" placeholder="メッセージを入力">
<button type="submit">送信</button>
</form>
</div>
WebSocket拡張を使えば、チャットのようなリアルタイム機能も実現できます。
6. Server Sent Events(SSE)
<div hx-ext="sse" sse-connect="/events" sse-swap="message">
<!-- サーバーからのイベントで更新される -->
</div>
サーバーからのプッシュ通知も属性一つで対応可能。
拡張機能
htmxには便利な拡張機能が用意されています。
json-enc - JSONでリクエストボディを送信
<script src="https://unpkg.com/htmx.org@2.0.8/dist/ext/json-enc.js"></script>
<form hx-post="/api/users" hx-ext="json-enc">
<input name="name" value="田中">
<button>送信</button>
</form>
フォームデータをJSONとして送信できます。
preload - リンクのプリロード
<script src="https://unpkg.com/htmx.org@2.0.8/dist/ext/preload.js"></script>
<a href="/page" hx-get="/page" preload="mouseover">
ホバーでプリロード
</a>
マウスオーバーで先読みしておくことで、体感速度が向上します。
注意点
いいことばかり書いてきましたが、htmxにも向き不向きがあります。
向いているケース
- 既存のサーバーサイドアプリに動的機能を追加したい
- 管理画面やダッシュボードの構築
- コンテンツ主体のWebサイト
- プロトタイプの素早い開発
- JavaScriptを最小限にしたい
向いていないケース
- 複雑な状態管理が必要なSPA
- オフライン対応が必要なアプリ
- 高度なアニメーションやインタラクション
- クライアント側で複雑な計算が必要な場合
個人的には、「8割のWebアプリはhtmxで十分」だと思っています。残りの2割(高度なSPA)にはReactやVueを使えばいい。
まとめ
正直なところ、htmxは「Webの原点回帰」という感じがしますね。
HTMLが本来持つべきだった能力を取り戻す。JavaScriptで複雑なことをやらなくても、シンプルなHTML属性で多くのことが実現できる。
以下の条件に当てはまるなら、試してみる価値は間違いなくあります:
- JavaScriptフレームワークの複雑さに疲れている
- サーバーサイドの言語を活かしたい
- 学習コストを抑えてモダンなUIを作りたい
- 既存のアプリに動的機能を追加したい
- シンプルなものが好き
46,700スター以上という数字が、その実用性を証明しています。
まずは既存のサイトに<script>タグを一行追加して、ボタン一つから試してみてください。その手軽さに驚くはずです。
公式サイト: https://htmx.org GitHub: https://github.com/bigskysoftware/htmx ドキュメント: https://htmx.org/docs