你以为 htmx 只是个玩具?今天 4.0 用 fetch() 把这件事彻底变了

用过 htmx 的人都知道,这玩意儿靠 HTML 属性就能发起 AJAX 请求,不用写一行 JS。但很多人不知道的是——htmx 2.x 内部用的是 XMLHttpRequest,也就是 20 多年前的方案。今天,htmx 4.0 正式发布了,最大的变化就是:XMLHttpRequest 没了,全面切换 fetch()。

这件事为什么重要?因为 fetch() 才是现代浏览器的网络基础。切换之后,htmx 的能力天花板直接被拉高了。

最大的破坏性变更:错误响应不再被忽略

htmx 2.x 有一个很反直觉的设计:服务器返回 4xx、5xx 状态码时,htmx 什么都不做,DOM 保持原样。这在某些场景下合理,但大多数时候你返回 422 表单错误,期望页面显示错误信息。

htmx 4.0 把这个改了。4xx 和 5xx 响应现在默认会 swap 进 DOM——也就是服务器返回什么 HTML,htmx 就把它塞进目标元素。要恢复旧行为,需要通过 hx-status 或者 htmx.config.noSwap 配置。

同时,四个错误事件(htmx:sendError、htmx:swapError、htmx:targetError、htmx:timeout)合并成了一个 htmx:error。

显式继承:属性不再自动向下传递

htmx 2.x 里,父元素的 hx-confirm、hx-target 这些属性会自动被子元素继承。这是一个方便的设计,但也是坑——不小心就会给不该出现的按钮绑上了确认对话框。

htmx 4.0 要求显式:用 :inherited 后缀标记需要继承的属性,不加就不会传下去。hx-disinherit 和 hx-inherit 都移除了,因为显式继承让它们没有必要。

历史记录不再缓存 DOM

点完后退按钮,htmx 2.x 会从 localStorage 恢复之前缓存的 DOM 快照。4.0 改成重新发请求拿页面再 swap。如果你想恢复旧行为,可以配置 htmx.config.history = “reload”。

新能力:morph swaps 和多目标更新

切换到 fetch() 之后,htmx 补上了几个一直缺的能力:

morph 置换算法(idiomorph)内置了,局部更新更智能,尽量复用现有 DOM 节点的状态,不完全替换。

新 <template hx-ext=”morph”> 标签支持单次响应同时更新页面多个不同目标区域,替代了旧版 out-of-band 的方案,而且顺序更合理——主内容先 swap,OOB 元素按文档顺序再处理。

流式扩展也补上了:hx-sse、hx-ws、hx-multipart 分别支持 Server-Sent Events、WebSocket、multipart/mixed 流式 HTML。还有一个新扩展 hx-live,做响应式 DOM 更新,对标 Alpine.js。

要不要升级?

官方策略很保守:npm 上 htmx 2.x 保持 latest 标签直到 2027 年初,4.0 暂时挂在 next 下,且 2.x 会继续维护。这意味着现有项目没有必要急着动。

如果决定升级,官方提供了 htmx-2-compat 扩展恢复旧行为,可以渐进迁移。还有一个命令行工具:

npx htmx.org@4.0.0 upgrade-check — ./templates

自动扫描代码中的废弃属性、事件名、显式继承问题。官方也发布了 4 个 LLM Agent Skill 文件(htmx-guidance、htmx-debugging、htmx-extension-authoring、htmx-upgrade-from-htmx2),方便 AI 编程工具理解 htmx 项目。

总结

htmx 4.0 的本质变化是网络层:XMLHttpRequest → fetch()。这不只是技术债清理——配合 morph swaps 和多目标更新,htmx 的能力边界已经从「渐进增强」扩展到了「SPA 替代方案」。对于之前因为 XMLHttpRequest 而对 htmx 持观望态度的前端工程师,4.0 是一个值得重新评估的节点。

下一步:用 upgrade-check 跑一下你的项目,看有多少破坏性变更,再决定是现在迁移还是继续用 2.x 等生态跟上。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 15 阅读