版本号不是手滑。2.0 发布时,作者 Carson Gross 承诺过「永远不会有 3.0」,意思是不会有破坏性变更。结果他们还是做了破坏性变更,为了不食言,干脆跳过 3,直接 4。有人管这叫「指数级版本号」,下一个大版本是 8。

玩笑归玩笑,4.0 是 8 个月开发的结果,核心变化有三条。
属性继承从隐式改为显式。这是升级工作量最大的一项。htmx 2 里放在父元素上的 hx-confirm 会自动传递到子元素的 hx-delete 上,跟 CSS 一样,好用但经常让人困惑。4.0 里必须加 :inherited 后缀才会继承,不加就不传。团队提供了一个 npx htmx.org@4.0.0 upgrade-check 命令行工具,能扫描模板文件找出所有需要加 :inherited 的地方。
事件名也标准化了。2.x 的事件名是慢慢长出来的,没有统一格式。4.0 全部改成 htmx:phase:action 三段式,比如 htmx:beforeRequest 变成 htmx:before:request,htmx:afterSwap 变成 htmx:after:swap。升级工具也能扫描旧事件名。
历史记录不再用 localStorage 缓存。2.x 的页面快照存 localStorage,第三方 JS 库的 DOM 变更会被一起存进去,恢复时 JS 逻辑没了但 DOM 残留还在,是大量 bug 的来源。4.0 改为回退时重新 fetch 页面再 swap,配合 HTTP 缓存,速度快且干净。如果需要本地缓存,官方提供了一个 hx-history-cache 扩展。
底层有一次大移植:从 XMLHttpRequest 切到了 fetch()。对大多数用户透明,但这是让扩展体系焕然一新的基础。
两个能打的新功能。第一是 Morph 交换——内置了 morphing swap,基于 idiomorph 算法改进,不是简单的「替换元素」,而是对比新旧 DOM 只更新变化的部分,能保留用户输入焦点和滚动位置。第二是 <hx-partial> 标签,类似 2.x 的 out-of-band swap 但语义清晰得多:一个响应里可以放多个 <hx-partial>,每个指定自己的 target 和 swap 策略,在同一个请求里同时更新多个区域。
扩展体系也翻新了。hx-preload 预加载、hx-download 原生文件下载、hx-sse/hx-ws/hx-multipart 三种流式扩展,还有一个 hx-live 来做前端脚本——团队自己写的小型脚本方案,对标 Alpine.js 但更贴合 htmx 的 DOM 驱动理念。
4.0 不会立即取代 2.x。npm 上 latest 标签仍指向 2.x,next 才指向 4.0,预计 2027 年初才会切换。官方给 2.x 的承诺是无限期支持,不用急着升级。
参考来源: