在 Gumroad,我们最近启动了一个名为 Helper 的新项目。作为 CEO,我最初对 在这个项目中使用 htmx 相当乐观,尽管有些团队成员热情不高。
我的乐观源于之前使用 React 的经验,React 常常感觉对我们的需求来说是大材小用。我认为 htmx 可以是一个很好的解决方案,让我们的前端保持超级轻量。
事实上,我在 Slack 中与团队分享了这种看法:
“https://htmx.org/ 可能是一种添加简单交互的方式”
起初,它看起来很有前途!正如我们 Gumroad 的一位工程师雄辩地指出的那样:
“HTMX 正式成为一个用来嘲笑 JS 生态圈变得多么复杂的梗——就像 tailwind 只是内联 CSS 的一种不同语法一样,HTMX 是内联 JS 的一种不同语法。”
然而,与 Tailwind(它已在我们工具包中找到位置)不同,htmx 无法满足我们的扩展需求,也无法为我们的客户带来最佳用户体验——至少对我们的用例来说是如此。
原因如下:
直觉和开发者体验:虽然在 htmx 中做正确的事是可能的,但我们发现 使用 Next.js 让一切正常运行更加直观和有趣。使用 Next.js 的开发过程感觉很自然, 而在 htmx 中,它常常感觉不自然且生硬。例如,在构建具有动态 验证和条件字段的复杂表单时,我们发现自己在编写复杂的服务器端逻辑来处理那些在 React 中 是简单客户端操作的事情。
用户体验限制: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,这对于构建我们想要的复杂用户体验来说 是一个非常合适的选择。我们对这个决定感到满意——目前如此。它使我们能够更快地行动,创造更具吸引力的用户 体验,并利用大量现有工具和库。
这次经历强化了一个宝贵的教训:虽然考虑轻量级替代方案很重要,但 选择能够伴随项目成长并支持你长期愿景的技术同样重要。对于 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 的方法,并可能在未来其优势更符合我们 需求的项目中考虑它。
话虽如此,随着需求的变化和新技术的出现,我们始终愿意重新评估我们的技术栈。谁知道 未来会带来什么?