8 月 28 日,htmx 4.0 正式发布。这个只有约 14KB、零依赖的 JavaScript 库,用 8 个月时间完成了对自身底层的一次彻底重写。

对不了解它的人来说,htmx 可能是个陌生的名字;但在前端圈子里,它一直是个特别的存在——一个“刻意不赶时髦”的库,却在 React、Vue 这些庞然大物的夹缝里,攒下了近 5 万 GitHub star。

用 HTML 属性,替代写 JavaScript

htmx 的理念一句话就能说清:交互不需要非得写 JavaScript,用 HTML 属性就够了。

你想让一个按钮点击后请求服务器、把返回的 HTML 塞进某个区域?不用写 fetch、不用管状态管理,只要给按钮加几个 hx- 开头的属性就行。它走的是“服务端驱动 HTML”(hypermedia)路线,主张把逻辑放回服务端,让前端回归简单。

这套哲学,天然站在了复杂 SPA(单页应用)框架的对立面。当整个行业都在往“前端工程化、状态管理、虚拟 DOM”这条路上狂奔时,htmx 选择了另一条看起来“过时”的路:相信 HTML 本身的力量。

4.0 改了什么:从 XHR 到 Fetch,从替换到“调和”

这次重写最核心的变化,是把底层从 XMLHttpRequest 换成了浏览器原生的 Fetch API。

这听起来像内部细节,但影响深远。XHR 是上世纪 90 年代末的老技术,它有个致命限制:浏览器必须缓冲完整个响应,htmx 才能把内容塞进页面。换成 Fetch API 之后,配合 ReadableStream,htmx 第一次实现了真正的 HTML 流式渲染——服务端返回的内容可以边到达、边显示,不用等完整响应。

另一个重要变化,是把原本作为扩展的 Idiomorph 并入核心,带来了 morph 交换模式。过去“替换”是把目标元素整个换掉;现在“调和”(morph)会把新内容合并进现有 DOM,保留原有节点。于是焦点不会乱跳、正在播放的视频不会中断、CSS 过渡依然顺滑。

还有一个容易被忽视、却最容易“坑人”的改动:属性继承变成了显式的。htmx 2 里,父元素设置的 hx-target 会自动传给所有子元素;htmx 4 里,你必须显式加上 :inherited 后缀才会生效。它不会报错——只是按钮突然就“不听话”了。这也是官方文档反复提醒开发者升级前先做审计的原因。

一个意味深长的插曲:npm 默认还是 2.x

htmx 4.0 已经发布,但如果你现在执行 npm install htmx,装到的仍然是 2.x——htmx 4 暂时被放在 next 标签里,要到 2027 年初才会成为默认。

作者 Carson Gross 的解释很能说明这个项目的性格:他不愿意让一次 major 版本升级,通过非版本化的 CDN 链接“偷偷”流进生产环境,让那些没有主动选择的开发者措手不及。为此,htmx 2 承诺“无限期支持”,没有任何强制迁移的截止线。

在一个追求“快速迭代、尽快升级”的行业里,这种“慢一点、稳一点”的发布方式,本身就是一种态度。

简单,从来不是过时

htmx 4.0 的发布,与其说是一次版本更新,不如说是一份宣言:在“前端越来越重”的今天,依然有人在认真维护那条“简单”的路。

它没有要取代 React 或 Vue 的野心,也不需要。它证明的是另一件事:当你在服务端渲染、用 HTML 属性就能搞定九成交互时,很多“必备”的复杂框架,可能本来就不是必需的。

14KB,零依赖,8 个月重写——htmx 用它的方式提醒了整个行业:技术的选择,从来不该只有“更大、更复杂”这一个方向。有时候,把东西做小、做简单,才是真正的本事。