HTMX 太酷了,我自己写了一个
摘要
本文探讨了 HTMX 这个库,它偏爱服务器端渲染的 HTML,而非大量使用 JavaScript 的前端。作者发现 HTMX 对于持久化的 UI 组件很有用,但最终出于个人对最小依赖的偏好,决定自己实现一套解决方案。
<p><a href="https://lobste.rs/s/8hiogg/htmx_is_so_cool_i_rolled_my_own">评论</a></p>
查看缓存全文
缓存时间: 2026/06/08 13:18
# HTMX 太酷了,我自己写了一个!
来源:https://dbushell.com/2024/04/16/htmx-and-modern-javascript/
纯人工创作 - 无AI辅助
2024年4月16日 星期二
[HTMX](https://htmx.org/) 现在很火。它拒绝现代 JavaScript UI,转而使用服务端渲染的 HTML。这并非新概念,而是对旧有思路的进化。它建立在 React 让前端变得臃肿之前我们做事情的方式之上。HTMX 常见的例子包括无限滚动、实时搜索结果等。这些功能我以前肯定用了一百种不同的方式实现。真希望十年前就有 HTMX。
HTMX 并不能解决 React 等试图解决的所有问题。甚至对我来说它显得有些受限。但*在这些限制之内*,HTMX 是金子。我喜欢 **Carson Gross**——HTMX 的作者——在最近的 [PodRocket 播客](https://podrocket.logrocket.com/htmx-v2-carson-gross) 中谈论 HTMX 的方式。他说 HTMX 不是“魔法子弹”,并且:
> 我认为 HTMX 背后的一些想法可能比 HTMX 本身更重要。
我也这么认为。
## 实验
我想给 HTMX 一个公平的尝试。光读文档是不够的。*实际使用*代码才是真正的考验,我找到了一个很好的 HTMX 应用场景。最近我重构了自己托管的[播客 Web 应用](https://git.dbushell.com/dbushell/sauropod)的服务器。之前的版本使用了 [SvelteKit](https://kit.svelte.dev/)。我是 SvelteKit 的粉丝,但对于较小的网站来说,它可能过于复杂。我用自己一直在捣鼓的 [DinoSsr](https://github.com/dbushell/dinossr/) 项目替换了 SvelteKit。我还用它来构建我的[静态站点](https://dbushell.com/2024/02/14/super-fast-builds/)和提供我的[书签博客](https://dbushell.com/2024/01/24/cotton-coder/)。
DinoSsr 主要是服务端。它可以提供前端的“孤岛”组件,但这些组件并不能实现完整的页面交互。这对我的音频播放器组件来说是个问题。当我导航翻页时,它需要保持存在,否则收听体验会立刻中断。让我们看看:
sauroPod 截图
sauroPod 截图
左侧的截图展示的是没有标注的 [sauroPod](https://git.dbushell.com/dbushell/sauropod) 设计。中间的截图突出显示了所有 Svelte 组件。SvelteKit 神奇地处理了所有 UI 更新和前端路由。这真的很棒;也许我应该留着它。右侧的截图突出显示了我的新构建。这里只有音频播放器组件有前端 JavaScript。DinoSsr 有意不尝试客户端路由。导航会重新加载整个页面,从而结束任何播放。这并不理想。
我意识到这里有机会使用 HTMX。我有几个页面只在上面截图中我用橙色高亮显示的 `<main>` 区域不同。使用 HTMX,我可以渐进式增强链接,并在不重新加载页面的情况下更新这个区域,从而保持音频组件完好无损。
我尝试了 HTMX,效果很好!然后我立刻移除了 HTMX,并决定自己写一个。但首先:
## 对 HTMX 的一些想法
在我的例子中,HTMX 替代了前端 Svelte。但不是像 React 那样的“即插即用”替代品。这是一种思维上的巨大转变。我觉得这很提神。虽然 HTMX 是以 JavaScript 库的形式提供的,用于渐进式增强前端,但 HTMX 的大部分实现是在后端完成的。HTMX 并没有规定后端的代码。你必须自带服务器模板和配置。提供 HTML 的 HTTP 请求实际上就是 HTMX 的 API。配置 HTTP 头以确保正确的缓存有一些细微差别。这些在[文档](https://htmx.org/docs/#caching)中都有说明,但我认为对于像我这样的 JavaScript 瘾君子来说,服务器相关文档应该更早介绍。
一个小抱怨:我不喜欢使用 `hx-*` 前缀的 HTML 属性,而应该使用 `data-*`(配合 [dataset](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset))。当有标准存在时,为什么还要使用非标准?一个更大的抱怨:HTMX 文档中有很多 `<div>` 示例:
```
<div hx-put="/messages" hx-target="#result">
Put To Messages
</div>
```
> 当用户点击这个 div 时,向 URL /messages 发起一个 PUT 请求,并将响应加载到 div 中
我是不是误以为这是 React 教程?用户不应该*点击* `<div>` 元素。在我看来,一些更高级的使用内联 JavaScript 的 HTMX 例子变得有点糟糕。这些例子展示了声明式属性模板的局限性。
撇开批评不谈,我认为 HTMX 提供了一套有限但有用的功能,可以增强许多常见的网页设计模式。如果我讨厌它,就不会花时间写博客了!
## 自己写一个
总之,在成功添加 HTMX 之后,我立刻移除了它!太有趣了,我决定用同样的想法写一个自己的迷你版本。我使用了相同的 `last-modified` 和 `if-modified-since` HTTP 头部以及 `304` 响应来缓存 fetch 请求。我使用了 `pushState`([MDN](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState))和 `popstate`([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event))来实现基本的历史集成。我添加了一些代码来提取和替换 `main` 元素。受 [HTMX 预加载扩展](https://htmx.org/extensions/preload/) 的启发,我使用指针事件构建了预加载功能。通过在 `click` 事件触发之前发起 fetch 请求,这带来了一点性能提升。我怀疑在使用我自己的实现过程中,会发现我遗漏的东西。目前它运行良好。
我的实验的[源代码](https://git.dbushell.com/dbushell/sauropod/src/branch/main/static/scripts/sauropod-state.js)在我的 Git 仓库中。它非常基础,但展示了浏览器端实际上需要多少 JavaScript。通过使用 HTMX——或者“我们在家用的 HTMX”——我的代码库变得更小、更简单了。
## 前端 JavaScript
对于除了最小网站以外的所有网站,模板和“组件”对于组织和复用代码几乎是必要的。这可以在服务端使用 PHP、Ruby、Go、任何语言,甚至 JavaScript 来完成。这需要在浏览器中复制吗?或者更糟,*只在*浏览器中?随着 React 等的流行,我们中许多人都停止问这个问题了。这个项目提醒我,答案是一个响亮的*不*。
前端 JavaScript 疲劳是真实存在的。我自己也犯了过度设计 JS UI 的错,尽管我更喜欢老式的服务端模板。我甚至不认为 HTMX 有那么好,但它背后的哲学让现代 JavaScript 开发者感到尴尬。为此我非常感激。
相似文章
我如何将 HTMX 与 Go 结合使用
这篇博文由 Alex Edwards 撰写,解释了如何将 HTMX 与 Go 集成以构建服务端渲染的 Web 应用程序,涵盖了模板结构、局部响应、重定向和错误处理。
从代码库中移除 React.js 并采用 HTMX 实现 UI 交互
Misago 论坛项目解释了其移除 React.js 并采用 HTMX 实现 UI 交互的决定,理由包括降低复杂度、提升性能以及更易于定制。
Let's make the worst Htmx
A blog post that humorously builds a minimal 'worst' clone of the htmx library, showing how to recreate its core behavior (triggers, fetches, and swaps) in vanilla JavaScript.
兄弟们,我在搞一个 HTML 流式传输库
作者正在开发一个 HTML 流式传输库,旨在平滑渲染 HTML 令牌,作为 Markdown 的替代方案,并对表格、SVG 和图表进行了改进。作者希望社区就还需要测试哪些功能提供意见。
使用 htmx 构建渐进增强的表单
关于使用 htmx 构建渐进增强表单的指南,涵盖诸如使用表单值、查询参数和按钮检测进行瞬态状态管理等技术。