群岛架构
Astro 帮助开创并推广了一种名为 群岛架构 的新前端架构模式。群岛架构的工作原理是将页面的大部分内容渲染成快速的静态 HTML,当页面上需要交互性或个性化时(例如,图片轮播),再添加较小的 JavaScript“群岛”。这避免了许多其他现代 JavaScript Web 框架中存在的、会减慢响应速度的庞大 JavaScript 负载。
“组件群岛”一词最初由 Etsy 的前端架构师 Katie Sylor-Miller 在 2019 年提出。这个想法随后被 Preact 的创建者 Jason Miller 在 2020 年 8 月 11 日的这篇文章中扩展和记录。
“群岛”架构的总体思路看似简单:在服务器上渲染 HTML 页面,并在高度动态的区域周围注入占位符或插槽 […] 然后这些区域可以在客户端被“注水”(hydrate)成小型的独立小部件,并重用它们在服务器上渲染的初始 HTML。
—— Jason Miller,Preact 创始人
该架构模式所基于的技术也被称为部分注水或选择性注水。
相比之下,大多数基于 JavaScript 的 Web 框架会将整个网站作为一个大型 JavaScript 应用程序(也称为单页应用程序,或 SPA)进行注水和渲染。SPA 提供了简单性和强大的功能,但由于大量使用客户端 JavaScript,导致页面加载性能不佳。
SPA 有其用武之地,甚至可以嵌入在 Astro 页面中。但是,SPA 缺乏选择性和策略性注水的原生能力,这使得它们对于当今 Web 上的大多数项目来说,是一个过于笨重的选择。
Astro 作为第一个内置选择性注水功能的主流 JavaScript Web 框架而广受欢迎,它使用了 Sylor-Miller 最初提出的相同的组件群岛模式。我们此后扩展并发展了 Sylor-Miller 的原始工作,这启发了一种类似的组件群岛方法来处理动态服务器渲染内容。
什么是群岛?
名为“什么是群岛?”的部分在 Astro 中,群岛是一个在静态 HTML 页面上的增强型 UI 组件。
客户端群岛是一个交互式的 JavaScript UI 组件,它与页面的其余部分分开进行注水,而服务器群岛则是一个 UI 组件,其动态内容与页面的其余部分分开在服务器上渲染。
为了优化页面加载,两种群岛都以每个组件为基础,独立运行昂贵或较慢的进程。
群岛组件
名为“群岛组件”的部分Astro 组件是你页面模板的构建块。它们会渲染成没有客户端运行时的静态 HTML。
可以将客户端群岛想象成一个漂浮在静态、轻量、服务器渲染的 HTML 海洋中的交互式小部件。服务器群岛可以用于添加个性化或动态的服务器渲染元素,例如已登录用户的个人资料图片。
静态内容,如文本、图片等
一个群岛总是与页面上的其他群岛隔离运行,一个页面上可以存在多个群岛。客户端群岛即使在不同的组件上下文中运行,仍然可以共享状态并相互通信。
这种灵活性使得 Astro 能够支持多种 UI 框架,如 React、Preact、Svelte、Vue 和 SolidJS。因为它们是独立的,你甚至可以在每个页面上混合使用多种框架。
虽然大多数开发者会坚持使用一个 UI 框架,但 Astro 支持在同一个项目中使用多个框架。这允许你:
- 为每个组件选择最适合的框架。
- 学习一个新框架而无需启动新项目。
- 即使在不同框架下工作,也能与他人协作。
- 将现有站点逐步转换为另一个框架,且无需停机。
客户端群岛
名为“客户端群岛”的部分默认情况下,Astro 会自动将每个 UI 组件渲染成纯 HTML 和 CSS,并自动剥离所有客户端 JavaScript。
<MyReactComponent />
这听起来可能很严格,但正是这种行为让 Astro 网站默认保持快速,并保护开发者免于意外发送可能减慢网站速度的不必要或不希望的 JavaScript。
将任何静态 UI 组件转变为交互式群岛只需要一个 client:*
指令。然后 Astro 会自动构建和打包你的客户端 JavaScript 以优化性能。
<!-- This component is now interactive on the page! The rest of your website remains static. --><MyReactComponent client:load />
有了群岛,客户端 JavaScript 只会为你使用 client:*
指令明确标记的交互式组件加载。
而且由于交互性是在组件级别配置的,你可以根据每个组件的用途处理不同的加载优先级。例如,client:idle
告诉组件在浏览器空闲时加载,而 client:visible
告诉组件仅在其进入视口时加载。
客户端群岛的优势
使用 Astro 群岛构建最明显的好处是性能:你的大部分网站被转换为快速的静态 HTML,JavaScript 只为需要它的单个组件加载。JavaScript 是按字节加载速度最慢的资源之一,所以每个字节都很重要。
另一个好处是并行加载。在上面的示例图中,低优先级的“图片轮播”群岛不需要阻塞高优先级的“页眉”群岛。两者并行加载并独立注水,这意味着页眉可以立即变得交互,而无需等待页面下方更重的轮播。
更棒的是,你可以告诉 Astro 每个组件确切的渲染方式和时机。如果那个图片轮播加载成本很高,你可以附加一个特殊的客户端指令,告诉 Astro 仅当轮播在页面上可见时才加载它。如果用户永远看不到它,它就永远不会加载。
在 Astro 中,由你作为开发者明确告诉 Astro 页面上的哪些组件需要在浏览器中运行。Astro 将只注水页面上确切需要的部分,并将其余部分保留为静态 HTML。
客户端群岛是 Astro 默认快速性能故事的秘诀!
服务端群岛
名为“服务器群岛”的部分服务器群岛是一种将昂贵或缓慢的服务器端代码移出主渲染过程的方法,使得结合高性能静态 HTML 和动态服务器生成组件变得容易。
将 server:defer
指令添加到页面上的任何 Astro 组件,即可将其转变为自己的服务器群岛。
---import Avatar from "../components/Avatar.astro";---<Avatar server:defer />
这将你的页面分解为更小的服务器渲染内容区域,每个区域都并行加载。
页面的主要内容可以立即用占位符内容(如通用头像)渲染,直到你的群岛自身内容可用。有了服务器群岛,拥有小块的个性化内容不会延迟一个原本是静态页面的渲染。
这种渲染模式被设计为可移植的。它不依赖于任何服务器基础设施,因此可以在任何主机上工作,从 Docker 容器中的 Node.js 服务器到你选择的无服务器提供商。
服务器群岛的优势
服务器群岛的一个好处是能够即时渲染页面中更具动态性的部分。这使得外部框架和主要内容可以被更积极地缓存,从而提供更快的性能。
另一个好处是提供卓越的访客体验。服务器群岛经过优化,加载速度快,通常甚至在浏览器绘制页面之前就已经加载。但在你的群岛渲染所需的短暂时间内,你可以显示自定义的回退内容,并防止任何布局偏移。
一个能从 Astro 服务器群岛中受益的网站例子是电子商务店面。虽然产品页面的主要内容不常改变,但这些页面通常有一些动态部分:
- 页眉中的用户头像。
- 产品的特价和促销活动。
- 用户评论。
通过为这些元素使用服务器群岛,你的访客将立即看到页面最重要的部分——你的产品。通用头像、加载动画和商店公告可以作为回退内容显示,直到个性化部分可用。