互動拆回 HTTP:htmx 讓你不需要前端框架也能活

用過 htmx 之後,你會發現一件事:很多互動根本不需要 client 端狀態,只是因為習慣開一整套 SPA,才把問題搞複雜了。

htmx 2.0 在 2024 年中正式發布,核心概念從第一天就沒變過:把 HTML attribute 當介面,讓 browser 拿著 HTTP request 去 server 要一段 HTML 片段,再局部更新 DOM。不需要 JSON、不需要 state store、不需要 serialise/deserialise,互動本質上就是 request/response,跟 1990 年代的 Web 模型一樣,只是換成 partial 更新而不是整頁刷新。

<!-- 按下按鈕,GET /tasks,把回傳的 HTML 塞進 #task-list -->
<button hx-get="/tasks" hx-target="#task-list" hx-swap="innerHTML">
  重新整理
</button>

<!-- 送出表單,POST /tasks,server 回傳更新後的清單片段 -->
<form hx-post="/tasks" hx-target="#task-list" hx-swap="outerHTML">
  <input name="title" />
  <button type="submit">新增</button>
</form>

server 那邊只要回 partial HTML,不需要特別的 API 層:

<!-- server 回傳這段就夠了 -->
<ul id="task-list">
  <li>整理文件</li>
  <li>寫測試</li>
</ul>

這個模式在 CRUD 後台、表單流程、workflow-heavy 的管理介面特別合適,因為這些東西的「狀態」原本就該在資料庫,不是在 browser 的記憶體裡。你不需要在 client 端同步 server 的資料,因為你每次都直接問 server 要最新的 HTML。


當然不是每個需求都適合。高互動的東西,比如即時協作編輯器、canvas 繪圖工具、需要 offline-first 的 PWA、或是 local state 極度複雜的儀表板,那些還是要 client 端狀態管理,強行用 htmx 會很痛苦。SPA 在對的場景就是對的工具,問題在於應該先問:「這個需求真的需要 SPA 嗎?」很多後台系統、內部工具、CRUD 介面,答案是不需要,只是大家反射性地去開 React/Vue/Svelte 而已。

htmx 讓你把預設值調回來:server render、HTTP 傳輸、HTML 當 payload,只有真正需要 client 互動的部分才引入 JS。這本身就是 hypermedia 的設計理念,htmx 只是把它包裝得更好操作。

重點整理

  • htmx 的核心:hx-* attribute 驅動 HTTP request,server 回傳 HTML 片段,browser 局部換 DOM,狀態留在 server。
  • 適合 CRUD 後台、表單流程、workflow-heavy 管理介面,不適合高互動、離線優先、或重 local state 的應用。
  • 把預設選項調回 server-driven,需要 client state 的地方再引入 SPA。
  • server 端不需要特別改架構,只要能回傳 HTML 片段就可以接入。
  • 工具崇拜會讓你把每個問題都用 SPA 解,先問需求,再選工具。

觀點 Sheng,內文 Claude 協助 · 列入 20260613 blog 翻新計劃,新漆未乾。