从代码库中移除 React.js 并采用 Htmx 进行 UI 交互。
Removing React.js from the codebase and adapting Htmx for UI interactivity (2023)

原始链接: https://misago-project.org/t/removing-reactjs-from-the-codebase-and-adapting-htmx-for-ui-interactivity/1267/

Misago 目前的架构依赖于“双重实现”,即页面需要通过 Django 模板和 React 组件分别渲染两次。这种冗余不仅增加了开发难度,也给需要自定义 HTML 的用户带来了困扰,同时导致代码库中逻辑和翻译的重复、文件臃肿,并在性能较差的设备上产生负面影响。 为了解决这些低效问题,作者提议放弃重型 React 前端,转而使用 **HTMX**。 HTMX 不会进行完整的客户端重渲染,而是将动态内容视为服务器渲染页面中的“岛屿”。当用户与组件交互(例如切换类别或发布回复)时,HTMX 只会从服务器获取必要的 HTML 片段,并将其替换到现有的 DOM 中。 这种方法具有以下优势: * **简洁性:** 消除了对冗余 JSON 序列化、React 组件和复杂构建步骤的需求。 * **可维护性:** 逻辑保持以 Django 为中心,使开发人员只需开发一次功能,无需重复劳动。 * **高性能:** 减小了初始下载体积,并将繁重的处理任务卸载到服务器端。 归根结底,通过利用 HTMX,Misago 既能保持高度的交互性,又能回归到更简单、更稳健且更易于维护的服务器端渲染模型。

这篇 Hacker News 帖子围绕 **HTMX** 与**传统 JavaScript 框架(React、Vue 等)**在处理 Web 交互方面的优劣展开了热烈讨论。 讨论的起因是一位开发者在尝试使用 HTMX 构建一个包含复杂筛选表单的产品列表页时的经历。他们发现,由服务器重新渲染大段 HTML 响应会导致明显的延迟。为了优化性能,他们对 UI 进行了拆解:将表单改为静态的客户端组件(使用 Alpine.js),仅通过 HTMX 保持结果区域的动态更新。 **辩论要点:** * **“合适工具”之争:** 支持者认为 HTMX 非常适合内容驱动的简单网站和 CRUD 应用,能够减少打包体积并降低复杂度。批评者则认为,在处理复杂的、高频状态管理(如实时聊天或深度同步组件)时,HTMX 会导致代码变得混乱(“面条式代码”),且缺乏像 React 那样强大的协调模型。 * **性能表现:** HTMX 的拥护者强调其更快的首屏加载速度和更低的客户端开销。质疑者则指出,服务端生成本身会带来延迟,且 React 的注水(hydration)和缓存策略已是成熟的高流量应用解决方案。 * **开发体验:** 一些开发者认为 HTMX 的“行为局部化”(locality of behavior)非常直观;而另一些开发者则认为,相较于现代框架的声明式状态管理,其指令式本质是一种倒退。
相关文章

原文

Here's how Misago works currently:

  1. You request https://misago-project.org.
  2. Django view gathers data to render list of threads.
  3. Django view renders template that contains almost complete HTML with list of threads, but also includes a JSON with same data used to render this HTML. And there is no interactivity because forms are disabled.
  4. JavaScript downloads.
  5. JavaScript runs, reads JSON embedded in the page's body and replaces most of HTML rendered from Django templates with HTML from React.js components. Buttons become active, and timestamps in UI swap.

This approach has some problems:

  • A lot of pages in Misago are implemented twice: as Django templates and React.js components.
  • People who start customizing HTML get burned because they edit Django templates and see their changes flash for a second on a site before being replaced by React.js HTML which they didn't know they also need to customize.
  • Every view accessible to both users and guests needs to be done twice: as Django view with templates, and as React.js route with components. It also requires an API and JSON serializers to power data fetching.
  • JSON serialization to pre-bake data for React.js app slows down response generation.
  • A large part of translation messages is duplicated, living in both django.po and djangojs.po files. JavaScript translation files also increase the initial download size.
  • Lots of JavaScript can kill performance, especially on older and slower mobile devices.
  • Enabling plugins to replace or inject custom HTML to the page requires for those plugins to implement both Django templates and React.js components. And Misago will need to implement a JavaScript build step as part of site build in misago-docker. Plugin devs need to know both.

I've considered two solutions to this problem:

  1. Drop Django views and templates, only keep those in minimal versions to keep search engine bots happy. Focus on implementing an API and having all UI as React.js app.
  2. Reduce Django to API and use JavaScript framework with serverside rendering, eg. Next.js or Remix.run.

But here's a thing: there's a lot of forum software out there that still does the old way of rendering as much as possible on the server and using some JavaScript on client to improve its interactivity here and there. And people are happy with that. And this approach has none of the above issues.

Internet forum software has plenty of interactivity, but this interactivity is isolated to specific places on the page. Moderation actions, watching a thread, writing a reply, seeing last notifications, voting in a poll. All this stuff can be achieved without React.js and was achieved without it for years before we've decided that full page reload is something that needs to be avoided.

Now, what's HTMX? HTMX is a tiny library that lets developers specify parts of HTML as dynamic islands that can be swapped by new server-rendered HTML on interaction. For example, list of actual threads is one such (large) island. With little bit of HTMX included in Django template, changing current category on threads list could pull new HTML from Django only for new threads list for selected category, while keeping rest of the page's HTMX (eg. already loaded search results in navbar) unchanged. Misago's backend code would only need to be changed to return only the HTML for this island when request comes from HTMX, instead of full page. There's no need to do any JSON serialization or write dedicated JavaScript or React.js.

HTMX is declarative way of doing $.get("url", "#outlet") we've did in jQuery 20 years ago. Or Rails Turbolinks. I can't believe I am writing this, but this is the way for forum software if you hate endless scrolling or want to keep things simple otherwise.

联系我们 contact @ memedata.com