论点:MPA - 多页应用
反论:SPA - 单页应用
合题:HDA - 超媒体驱动应用
超媒体驱动应用 (HDA) 架构是一种新/旧的方法,用于构建 Web 应用。它将传统多页应用 (MPA) 的简易性和灵活性与单页应用 (SPA) 的更好用户体验相结合。
HDA 架构通过扩展 Web 的现有 HTML 基础设施来实现这一目标,从而允许超媒体开发者创建更强大的基于超媒体的交互。
遵循 REST 架构约束的概念,有两个这样的约束特征化了 HDA 架构:
HDA 使用声明式、嵌入 HTML 的语法而不是命令式脚本来实现更好的前端交互性
HDA 以超媒体(即 HTML)的形式与服务器交互,而不是非超媒体格式(例如 JSON)
通过采用这两个约束,HDA 架构以 SPA 架构无法实现的方式保持在 Web 的原始REST-ful 架构之内。
特别是,HDA 继续使用超媒体作为应用状态引擎 (HATEOAS),而大多数 SPA 则放弃 HATEOAS,转而使用客户端模型和数据(而非超媒体)API。
考虑 htmx 的活跃搜索 示例:
<h3>
Search Contacts
<span class="htmx-indicator">
<img src="/img/bars.svg"/> Searching...
</span>
</h3>
<input class="form-control" type="search"
name="search" placeholder="Begin Typing To Search Users..."
hx-post="/search"
hx-trigger="keyup changed delay:500ms, search"
hx-target="#search-results"
hx-indicator=".htmx-indicator">
<table class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
</thead>
<tbody id="search-results">
</tbody>
</table>
这是一个通常与 SPA 相关的 UX 模式:当用户输入时,经过短暂暂停后,搜索结果将填充下面的结果表。然而,在这种情况下,它完全在 HTML 内实现,并与 HTML 的方式一致。
此示例有效地展示了 HDA 的基本特征:
该功能的 frontend 完全通过声明式 htmx 属性指定,直接在 HTML 中
与服务器的交互通过 HTTP 和 HTML 完成:发送 HTTP POST 请求到服务器,服务器返回 HTML,htmx 将此 HTML 插入到 DOM 中
按需代码 是 Web 原始 REST-ful 架构的可选约束。
类似地,HDA 架构有一个最终的可选约束:
这解决了 Roy Fielding 在其论文中提到的关于按需代码的担忧:
然而,(按需代码) 也会降低可见性,因此在 REST 中仅为可选约束。
通过将按需代码(脚本)直接嵌入 HTML,可见性得到增强,满足了行为局部性 软件设计原则。
满足此第三个约束的三种脚本方法是 hyperscript、AlpineJS 和 VanillaJS(当直接嵌入 HTML 元素时)。
以下是每种方法的示例:
<!-- hyperscript -->
<button _="on click toggle .red-border">
Toggle Class
</button>
<!-- Alpine JS -->
<button @click="open = !open" :class="{'red-border' : open, '' : !open}">
Toggle Class
</button>
<!-- VanillaJS -->
<button onclick="this.classList.toggle('red-border')">
Toggle Class
</button>
在 HDA 中,超媒体 (HTML) 是构建应用的主要媒介,这意味着:
与服务器的所有通信仍通过 HTTP 请求管理,并以超媒体 (HTML) 响应
脚本主要用于增强应用的前端体验
脚本增强了现有的超媒体 (HTML),但不会取代它或颠覆 HDA 的基本 REST-ful 架构。
以下库允许开发者创建 HDA:
以下脚本库,当适当使用时,可补充 HDA 方法:
HDA 架构是两种先前架构的综合:原始多页应用 (MPA) 架构和(相对)较新的单页应用架构。
它试图捕捉两者的优势:MPA 的简易性和可靠性,具有使用超媒体作为应用状态引擎 的REST-ful 架构,同时提供与 SPA 在许多情况下相当的更好用户体验。