Htmx 4.0

Htmx 4.0

htmx 4.0.0 Release

The htmx team is very happy to announce the release of htmx 4.0.0! This is the culmination of 8 months of work (plus a game) and we are very happy with the results. htmx 4.0.0 发布 htmx 团队非常高兴地宣布 htmx 4.0.0 正式发布!这是我们 8 个月工作(外加一个游戏开发)的结晶,我们对最终成果感到非常满意。

The idea of htmx 4 started to germinate when I decided to create fixi and, in doing so, got more familiar with the fetch() API and async programming in JavaScript. (htmx had always used XMLHttpRequest due to backwards compatibility issues.) htmx 4 的构想始于我决定创建 fixi 的时候,在开发过程中,我更加熟悉了 JavaScript 中的 fetch() API 和异步编程。(由于向后兼容性问题,htmx 此前一直使用 XMLHttpRequest。)

One chance evening I was contacted by Christian, who had some interesting ideas around streaming HTML that got me thinking that moving the internals to fetch() would simplify things for him and for the library in general. After a bit of work I managed to get Michael and Alex on board, and we were off to the races. 在一个偶然的夜晚,Christian 联系了我,他提出了一些关于流式 HTML 的有趣想法,这让我意识到将内部实现迁移到 fetch() 将会简化他的工作,也能让整个库变得更简洁。经过一番努力,我成功邀请了 Michael 和 Alex 加入,随后我们便全速投入了开发。

Development has been very smooth. We started a port of fixi + the htmx test suite. Over time, we rediscovered why htmx did many of the things that it did and moved our new implementation closer and closer to the old one. At this point the behavioral differences between 2.x and 4.x are relatively small and where they do diverge we have made explicit choices that we feel will put htmx-based applications in a good spot for being 100-year web services. 开发过程非常顺利。我们首先移植了 fixi 和 htmx 的测试套件。随着时间的推移,我们重新发现了 htmx 过去许多设计决策背后的原因,并不断将新实现向旧版本靠拢。目前,2.x 和 4.x 之间的行为差异相对较小;在出现分歧的地方,我们做出了明确的选择,我们相信这将使基于 htmx 的应用程序能够更好地适应“百年 Web 服务”的目标。

Note that we are not marking 4.0 as latest in NPM because we do not want to force-upgrade users who are relying on non-versioned CDN URLs for htmx. Instead, 2.x will remain latest and the 4.0 line will remain next until some point in early 2027. The website, however, will reference 4.0. 请注意,我们没有将 4.0 在 NPM 中标记为 latest,因为我们不想强制升级那些依赖非版本化 CDN URL 的用户。相反,2.x 将保持为 latest,而 4.0 系列将保持为 next,直到 2027 年初的某个时间点。不过,官方网站将会引用 4.0 版本。


Major Changes

As mentioned above, htmx 4, from a user’s viewpoint, is almost identical to htmx 2. There are three major changes: 主要变更 如上所述,从用户的角度来看,htmx 4 与 htmx 2 几乎完全相同。主要有三个重大变更:

  1. Attribute inheritance is now explicit by default rather than implicit by default (this is the biggest upgrade item).

  2. The htmx event names have been standardized & cleaned up. Some advanced users may need to change the events they listen for.

  3. History support now does not use localStorage by default (which was a cause of many support headaches). Most people won’t notice this at all. Internally, we migrated from XMLHttpRequest to fetch() but that should be transparent for most users of htmx.

  4. 属性继承现在默认为显式,而不是隐式(这是最大的升级项)。

  5. htmx 事件名称已标准化并进行了清理。一些高级用户可能需要更改他们监听的事件。

  6. 历史记录支持现在默认不再使用 localStorage(这曾是许多技术支持问题的根源)。大多数用户根本不会注意到这一点。 在内部,我们从 XMLHttpRequest 迁移到了 fetch(),但这对于大多数 htmx 用户来说应该是透明的。


Attribute Inheritance

In htmx 2 many attributes were “inherited” by default. This allows you to place attributes on parent elements and their behavior will apply to child elements. This behavior, which came from the intercooler.js days, was inspired by CSS and, unsurprisingly, worked out about the same as CSS: powerful but difficult to understand at times. 属性继承 在 htmx 2 中,许多属性默认是“继承”的。这允许你将属性放在父元素上,其行为会应用于子元素。这种源自 intercooler.js 时期的行为受到了 CSS 的启发,不出所料,它的工作方式与 CSS 类似:功能强大,但有时难以理解。

In htmx 4 attributes are not inherited unless you explicitly say so by adding an :inherited after the attribute name: 在 htmx 4 中,除非你在属性名称后添加 :inherited 来显式声明,否则属性不会被继承:

<!-- htmx 2 -->
<div hx-confirm="Are you sure?">
  <button hx-delete="/item/1">Delete</button>
</div>

<!-- htmx 4 -->
<div hx-confirm:inherited="Are you sure?">
  <button hx-delete="/item/1">Delete</button>
</div>

This will be the largest upgrade burden in migrating from htmx 2 to htmx 4. To make things easier, we have provided a command line tool to find places you need to mark as inherited. Note that attributes like hx-disinherit, etc. are no longer required and should be removed. 这将是从 htmx 2 迁移到 htmx 4 时最大的升级负担。为了简化流程,我们提供了一个命令行工具来查找需要标记为继承的地方。请注意,hx-disinherit 等属性不再需要,应该移除。


Events

The events triggered by htmx 2 had grown organically over the life of the library and were not particularly well organized, making it difficult to know exactly which event was fired when. In htmx 4, all events now follow htmx:phase:action[:sub-action]. 事件 htmx 2 触发的事件随着库的生命周期有机增长,组织得并不特别好,导致很难确切知道何时触发了哪个事件。在 htmx 4 中,所有事件现在都遵循 htmx:phase:action[:sub-action] 的命名规范。

(Table omitted for brevity, please refer to official docs for the full mapping) (表格从略,完整映射请参考官方文档)

In addition, the following changes were made:

  • Most error events collapse into htmx:error.
  • HTTP error responses fire htmx:response:error.
  • The htmx:xhr:* events are removed. htmx 4 uses fetch().
  • The htmx:validation:* events are removed in favor of native browser form validation. 此外,还进行了以下更改:
  • 大多数错误事件合并为 htmx:error
  • HTTP 错误响应触发 htmx:response:error
  • htmx:xhr:* 事件被移除。htmx 4 使用 fetch()
  • htmx:validation:* 事件被移除,转而支持原生的浏览器表单验证。

History

History support has always been included in htmx, allowing you to implement back-button aware actions with simple attributes. In htmx 2, a cache in localStorage was used to snapshot pages for restoration. Unfortunately a large source of issues was that this snapshot could include DOM mutations by 3rd party JavaScript libraries. 历史记录 历史记录支持一直包含在 htmx 中,允许你通过简单的属性实现感知“后退”按钮的操作。在 htmx 2 中,localStorage 中的缓存被用于对页面进行快照以供恢复。不幸的是,一个主要的问题来源是,这个快照可能包含第三方 JavaScript 库所做的 DOM 变更。

htmx 4 does not cache pages in localStorage. On back navigation htmx re-fetches the page and swaps it into <body>, or into the [hx-history-elt] element if one is present. If you want local caching instead, we now ship a very complete hx-history-cache extension. htmx 4 不会在 localStorage 中缓存页面。在后退导航时,htmx 会重新获取页面并将其交换到 <body> 中,或者如果存在 [hx-history-elt] 元素,则交换到该元素中。如果你需要本地缓存,我们现在提供了一个非常完善的 hx-history-cache 扩展。


New Features

There are two big new features in htmx 4: 新特性 htmx 4 有两个重大的新特性:

Morph Swaps We now support morphing swaps out of the box with htmx. Michael has done great work improving on that algorithm and integrating it seamlessly into htmx. Morph Swaps (形态交换) 我们现在在 htmx 中开箱即用地支持形态交换(Morphing Swaps)。Michael 在改进该算法并将其无缝集成到 htmx 中方面做了出色的工作。

<hx-partial> Another major new feature is the <hx-partial> tag. This tag is similar to out-of-band swaps, but is much clearer when you want to do something beyond just replacing a single element. <hx-partial> 另一个主要的新特性是 <hx-partial> 标签。该标签类似于带外交换(out-of-band swaps),但当你想要做的不仅仅是替换单个元素时,它会清晰得多。


Extensions

Switching to fetch() internally let us rethink how extensions can and should work, and sparked the creation of many new extensions, for example:

  • hx-preload - preload content to speed requests up.
  • hx-download - native, fetch-based file downloads.
  • hx-alpine-compat - smooths over compatibility. 扩展 内部切换到 fetch() 让我们重新思考了扩展应该如何工作,并激发了许多新扩展的创建,例如:
  • hx-preload - 预加载内容以加速请求。
  • hx-download - 基于 fetch 的原生文件下载。
  • hx-alpine-compat - 平滑兼容性处理。