何时使用超媒体?

Carson Gross

然而,权衡是统一接口会降低效率,因为信息以标准化形式传输,而不是以特定于应用程序需求的形式传输。REST 接口旨在针对大型超媒体数据传输效率,针对 Web 的常见情况进行优化,但会导致接口不适合其他形式的架构交互。

- Roy Fielding, https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5

我们显然是超媒体的粉丝,并且认为它可以至少部分地解决当今 Web 开发世界面临的许多问题。

借助htmx及其提供的额外 UX 可能性,我们相信许多现代 Web 应用程序可以使用 HTML 和超媒体范式构建。

话虽如此,与所有技术选择一样,超媒体也存在权衡。在本文中,我们将为你提供一些方法,以思考超媒体是否适合你正在构建的应用程序或功能。

#过渡应用程序和超媒体

在深入探讨何时使用超媒体之前,我们想澄清一下,在构建 Web 应用程序时,采用超媒体不是一个非此即彼的决定。毕竟,即使是最单页的单页应用程序也使用超媒体:作为引导机制,启动应用程序。

在 Rich Harris 的演讲SPA 是否毁掉了 Web中,他提出了“过渡”应用程序的概念,即混合了超媒体和非超媒体(SPA)概念的应用程序。我们已经在这里详细回应了 Harris 先生的演讲,但足以说明我们强烈同意他关于 Web 开发的务实“过渡”方法是最佳的:你应该为正在进行的特定工作使用合适的工具。

我们可能与 Harris 先生意见不一致的地方在于,在超媒体可以有效地实现的功能与需要更复杂客户端方法的功能之间,“界限”在哪里。我们认为,借助 htmx,超媒体可以比当今许多 Web 开发人员认为的还要强大。并且,对于许多应用程序来说,它可以满足许多或所有 UX 需求。

#超媒体:适合以下情况…

#…如果你的 UI 主要包含文本和图像

史上最棒的 htmx 演示中,Contexte 的 David Guillot 展示了用 htmx 替换 React 如何使代码库减少了 67%,以及其他令人惊叹的结果。

尽管我们很想说每个从 React 转向 htmx 的团队都会体验到这些结果,但事实是 Contexte Web 应用程序非常适合超媒体风格。

Contexte 如此适合超媒体的原因是,它是一个媒体导向的 Web 应用程序,显示包含文本和图像的阅读文章。它具有复杂的过滤机制和其他便利功能,但应用程序的核心是显示和分类文章。这正是超媒体的用途,这也是 htmx 和超媒体在他们的应用程序中如此有效的原因。

#…如果你的 UI 是 CRUD 类型的

超媒体在另一个领域也具有悠久的成功历史,即CRUD类型的 Web 应用程序,以Ruby on Rails风格为例。如果你的主要应用程序机制是显示表单并将表单保存到数据库中,那么超媒体可以很好地发挥作用。

此外,借助 htmx,它也可以非常流畅,而不仅仅局限于许多服务器端应用程序采用的简单列表视图/详情视图方式。

#…如果你的 UI 是“嵌套”的,并且更新主要发生在定义良好的块内

超媒体开始变得有点不稳定的地方在于,当你遇到跨越屏幕结构区域的 UI 依赖关系时。一个很好的例子(也是讨论超媒体方法时经常出现的问题)是 GitHub 上“问题”选项卡上显示的问题数量。很长一段时间,当你在 GitHub 上关闭一个问题时,选项卡上的问题数量没有正确更新。通常(尽管不完全是),GitHub 使用超媒体风格的应用程序。

“啊哈!”,SPA 爱好者会感叹道,“看,即使是 GitHub 也无法正确处理这个问题!”

好吧,GitHub 已经修复了这个问题,但它确实表明了超媒体方法的一个问题:如何干净地更新 UI 的不同部分?htmx 提供了几种技术来解决这个问题,Contexte 在他们的演讲中讨论了如何使用事件方法干净地处理这种情况。

但是,让我们承认,这是一个超媒体方法可能出现问题的领域。为了避免这个问题,一个可能的策略是将给定资源的依赖元素在应用程序的屏幕上的给定区域或区域内进行共同定位。

例如,考虑一个联系人应用程序,其显示和编辑联系人的详细信息屏幕包含

此 UI 可以按以下方式布局

Nested Example

在这种情况下,每个子部分都可以拥有自己专用的超媒体端点

这里诀窍在于,电子邮件和电话数量与其集合共同定位在屏幕上,这使你可以在进行相应集合修改时定位仅特定区域进行更新。所有数据依赖关系都共同定位在一个可以通过单个、简单且显而易见的 target 进行更新的区域内,并且它们在被替换时不会相互干扰。

每个区域实际上形成了一个服务器端组件,独立于屏幕上的其他区域,并且它们都嵌套在一个更广泛的联系人详细信息用户界面中。

#附注:UI 驱动的超媒体 API

请注意,在这种情况下,我们的超媒体 API(即我们的端点)是由 UI 驱动的:我们希望实现特定的 UI 布局,并根据该布局调整我们的 API。如果 UI 发生改变,我们毫不犹豫地完全改变我们的 API 以满足新的需求。这是使用超媒体进行开发的独特之处,我们在这里更详细地讨论了它

当然,可能存在不允许以这种方式对依赖元素进行分组的 UI 需求,并且如果上面提到的技术不令人满意,那么可能是时候考虑其他方法了。

超媒体优于其他选项的最后一个领域是,当你需要“深层链接”(即超出登录页面的应用程序链接)时,或者当你需要出色的首次渲染性能时。

由于超媒体是 Web 的自然语言,并且由于浏览器在给定 URL 时非常擅长渲染 HTML,因此这种方法对于诸如这些之类的“传统” Web 功能来说是难以超越的。

#超媒体:不适合以下情况…

#…如果你的 UI 具有许多动态的相互依赖关系

正如我们在上面关于“嵌套”UI 的部分中所讨论的,超媒体可能出现问题的一个领域是,当许多 UI 依赖关系分布在你的 UI 中,并且你无法承受“更新整个 UI”的代价时。这就是 Roy Fielding 在本文开头引言中所指出的:Web 被设计用于大型超媒体数据传输,而不是用于大量小型数据交换。

对于超媒体来说,尤其难以处理的是,当这些依赖关系是动态的时,即它们依赖于在服务器端渲染时无法确定的信息。一个很好的例子是电子表格:用户可以在单元格中输入任意函数,并动态地在屏幕上引入各种依赖关系。

(但是,请注意,对于许多应用程序来说,“可编辑行”模式是更通用电子表格行为的另一种可接受的替代方案,并且这种模式通过将编辑隔离在边界区域内,可以很好地与超媒体配合使用。)

#…如果你需要离线功能

超媒体分布式架构在很大程度上依赖于服务器端来渲染资源的表示形式。当服务器关闭或无法访问时,架构显然会遇到问题。可以使用服务工作者来处理离线请求(尽管这是一个复杂的选择),并且也很容易检测到超媒体应用程序何时处于离线状态,并显示离线消息,就像许多厚客户端应用程序一样。

但是,如果你的应用程序需要在离线环境中具有完整的功能,那么超媒体方法将不可接受。

#…如果你的 UI 状态更新非常频繁

如果您的 UI 状态频繁更新,超媒体就不是一个好的方法。一个很好的例子是一个需要捕捉鼠标移动的在线游戏。在鼠标移动和 UI 更新之间插入一个超媒体网络请求将无法正常工作,您最好编写自己的游戏客户端状态管理,并使用其他技术与服务器同步。

当然,您的游戏也可能有一个设置页面,而该设置页面可能比您用于游戏核心的解决方案更适合使用超媒体。在过渡式风格中混合使用不同的方法并没有什么问题!

然而,我们应该注意到,将 SPA 组件嵌入到更大的超媒体体系结构中通常比反过来更容易。孤立的客户端组件可以通过事件与更广泛的超媒体应用程序进行通信,就像拖放 Sortable.js + htmx示例中演示的那样。

#…如果您的团队没有参与

不选择超媒体的最后一个原因不是技术上的,而是社会学的:目前,超媒体在网页开发中并不受欢迎。许多公司已经采用 React 作为他们构建 web 应用程序的标准库。
许多开发人员和顾问已经将自己的职业生涯押在了 React 上。许多招聘经理从未听说过超媒体,更不用说 htmx 了,但他们习惯性地在他们发布的每一个职位中都写上了 React。招募 React 开发人员无疑要容易得多!

虽然这令人沮丧,但这是一个真实现象,我们应该怀着谦卑的态度铭记这一点。虽然 Contexte 能够快速有效地在 htmx 中重写他们的应用程序,但并非所有团队都像他们一样小、灵活和充满热情,也并非所有应用程序都像 htmx 那样适合这种方法。也许最好是在边缘采用超媒体,也许首先是用于内部工具,以证明其价值,然后才能更广泛地使用它。

#结论

我们经常被问到:“好吧,那么什么样的应用程序**不适合**使用 htmx”。我们更喜欢使用“过渡式”应用程序概念,从功能的角度考虑问题,但对于某些流行的应用程序,在思考使用超媒体还是其他方法时,心中有一些大致的概念是有帮助的。

举两个我们认为可以干净地使用超媒体实现的著名应用程序的例子,比如TwitterGMail。这两个 web 应用程序都是以文本和图像为主,更新粒度较粗,因此非常适合超媒体方法。

两个著名的 web 应用程序例子,它们**不适合**使用超媒体方法,是Google SheetsGoogle Maps。Google Sheets 中可能包含大量状态,并且许多单元格之间存在相互依赖关系,因此在每次单元格更新时发出服务器请求是不可行的。另一方面,Google Maps 对鼠标移动做出快速响应,根本无法承受每次鼠标移动都进行服务器往返的代价。这两个应用程序都需要比超媒体所能提供的更复杂的客户端设置。

当然,绝大多数 web 应用程序都没有达到这些例子的规模和复杂程度。并且几乎每一个 web 应用程序,即使是 Google Sheets 或 Google Maps,都有某些部分可能更适合使用超媒体方法:更简单、更快、更简洁。

将超媒体作为您工具箱中的工具,即使它没有成为您最喜欢的锤子,也将提高您作为 web 开发人员解决工程问题的能力。这种方法有很好的理论基础,对许多应用程序有实际优势,并且与其他方法不同,它“顺应”了 web 的发展趋势。

</>