在 Gumroad,我们最近启动了一个名为 Helper 的新项目。作为 CEO,我最初对在这个项目中使用 htmx 非常乐观,尽管团队中的一些成员不太热情。
我的乐观源于之前使用 React 的经验,它常常感觉对我们的需求来说太过复杂了。我认为 htmx 可以是一个好解决方案,让我们的前端保持超级轻量。
事实上,我在 Slack 中与团队分享了这种想法:
“https://htmx.cndocs.org/ 可能是添加简单交互的一种方式,用于起步”
最初,它看起来很有前景!正如我们 Gumroad 的一位工程师雄辩地指出的:
“HTMX(官方上)是一个用来嘲笑 JS 生态系统变得过于复杂的 meme——就像 tailwind 只是内联 CSS 的另一种语法一样,HTMX 是内联 JS 的另一种语法。”
然而,与 Tailwind 不同,后者已经在我们的工具包中找到了位置,htmx 并没有为我们的用途扩展,也没有为我们的客户带来最佳用户体验——至少在我们的用例中是这样。
原因如下:
直观性和开发者体验:虽然在 htmx 中做到正确的事情是可能的,但我们发现使用 Next.js 来让一切正常工作要直观得多,也更有趣。使用 Next.js 的开发过程感觉很自然,而使用 htmx 时,它常常感觉不自然且勉强。例如,在构建带有动态验证和条件字段的复杂表单时,我们发现自己需要编写复杂的服务器端逻辑来处理在 React 中本可以轻松实现客户端操作的事情。
UX 限制:htmx 最终将我们的应用推向了 Rails/CRUD 风格,这导致了默认情况下非常糟糕(或者至少是乏味且通用的)用户体验。我们发现自己不断与这种倾向作斗争,这适得其反。例如,为我们的工作流构建器实现拖放界面在使用 htmx 时证明是一个重大挑战,需要一些感觉笨拙的变通方法,而与使用 React 库所能实现的流畅体验相比就差远了。
AI 和工具支持:值得注意的是,AI 工具对 Next.js 非常熟悉,但对 htmx 则不然,这是由于缺乏开源训练数据。这类似于 Rails 面临的问题。虽然这不是一个致命问题,但它确实影响了我们的开发速度以及寻找解决方案的便利性。当我们遇到问题时,React/Next.js 丰富的资源让故障排除变得更快。
可扩展性担忧:随着项目的复杂性增长,我们发现 htmx 难以跟上我们的需求。最初吸引我们的简单性开始感觉限制性,当我们尝试实现更复杂的交互和状态管理时。例如,当我们添加实时协作和复杂数据可视化等功能时,使用 htmx 的服务器中心方法管理多个组件的状态变得越来越困难。
社区和生态系统:React/Next.js 生态系统庞大且成熟,为我们遇到的几乎任何问题提供了解决方案。使用 htmx 时,我们常常发现自己需要重新发明轮子或在功能上妥协。这在需要集成第三方服务和库时尤为明显,这些服务和库通常有 React 绑定,但没有 htmx 等价物。
最终,我们转向了 React/Next.js,这对于构建我们一直在寻找的复杂 UX 来说非常合适。我们对这个决定很满意——目前为止。它让我们能够更快地前进,创建更吸引人的用户体验,并利用丰富的现有工具和库。
这次经历强化了一个宝贵的教训:虽然考虑轻量级替代方案很重要,但同样关键的是选择能够随着项目增长并支持长期愿景的技术。对于 Helper,React 和 Next.js 证明了这是正确的选择。
自从我们转向那里以来,我们已经能够认真升级我们核心客户的应用用户体验。
拖放功能:我们工作流构建器的关键功能之一是通过拖放重新排序步骤。虽然使用 htmx 实现拖放是可能的,但我们发现可用的解决方案感觉笨拙,需要大量的自定义 JavaScript。相比之下,React 生态系统提供了像 react-beautiful-dnd 这样的库,只需最少的设置就能提供流畅、可访问的拖放。
复杂状态管理:每个工作流步骤都有自己的配置集和条件逻辑。当用户编辑这些时,我们需要实时更新 UI 以反映变化及其对其他步骤的影响。使用 htmx,这将需要大量的服务器往返或复杂的客户端状态管理,这违背了 htmx 的服务器中心理念。React 的状态管理解决方案(如 useState 或更高级的选项如 Redux)让这变得简单得多。
动态表单生成:每个步骤类型的配置不同,并且可以根据用户输入变化。使用 React 的组件模型生成这些动态表单并处理它们的状态要直观得多。使用 htmx,我们发现自己需要编写更复杂的服务器端逻辑来生成和验证这些表单。
实时协作:虽然在该截图中不可见,但我们实现了允许多个用户同时编辑工作流的功能。使用 WebSockets 和 React 实现这个相对简单,而使用 htmx,则需要更复杂的服务器端逻辑和自定义 JavaScript 来处理实时更新。
性能优化:随着工作流变得更大和更复杂,我们需要对渲染优化进行精细控制。React 的虚拟 DOM 和像 useMemo 和 useCallback 这样的钩子允许我们以 htmx 中不太容易或直观的方式优化性能。
重要的是要注意,虽然这些挑战在使用 htmx 时并非不可克服,但我们发现解决它们常常让我们偏离 htmx 的优势,转向在 JavaScript 密集环境中感觉更自然解决方案。这种认识是我们决定切换到 React 和 Next.js 的关键因素。
我们承认 htmx 可能非常适合许多项目,尤其是那些具有更简单交互模型或基于现有服务器渲染应用的项目的项目。我们的经验并不否定其他人从 htmx 中发现的好处。关键是理解项目的具体需求,并选择最符合这些需求工具。
在我们的案例中,Helper 界面的复杂、有状态性质使 React 和 Next.js 成为更好的选择。然而,我们继续欣赏 htmx 的方法,并可能在未来项目中考虑它,那时它的优势更符合我们的需求。
话虽如此,我们始终愿意随着需求演变和新技术的出现重新评估我们的技术栈。谁知道未来会带来什么?