跳转到内容

群岛架构

Astro 帮助开创并推广了一种新的前端架构模式,称为 群岛架构。群岛架构的工作原理是将大部分页面渲染为快速且静态的 HTML,并在页面上需要交互或者是个性化的区域(例如,轮播图),添加上更小的 JavaScript “群岛”。这种方式避免了单体 JavaScript 负载对于许多其他现代的 JavaScript Web 框架响应速度的影响。

“Etsy” 的前端架构师 Katie Sylor-Miller 在 2019 年首次创造了 “组件群岛” 这个术语。随后,Preact 的创造者 Jason Miller 在 2020 年 8 月 11 日扩展了这个概念,并在 这篇文章 中进行了记录。

“群岛” 架构的总体思想看似简单:在服务器上渲染 HTML 页面,并在高度动态的区域周围注入占位符或插槽 […] 这些区域随后可以在客户端 “激活” 成为小型独立的小部件,重用它们服务器渲染的初始 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 海洋中。可以为个性化或动态服务器渲染元素添加服务器岛屿,例如已登录访客的个人资料图片。

页头(可交互岛屿)

静态内容(比如文本、图片…)

来源:群岛架构:Jason Miller

单个岛屿始终独立于页面上的其他岛屿运行,且一个页面上可以存在多个岛屿。尽管客户端岛屿在不同的组件上下文中运行,但它们仍然可以共享状态并相互通信。

这种灵活性使得 Astro 能够支持多个 UI 框架,如 ReactPreactSvelteVueSolidJS。由于它们是独立的,你甚至可以在每个页面上混合使用多种框架。

默认情况下,Astro 会自动将每个 UI 组件渲染成仅包含 HTML 和 CSS 的形式,并自动剥离掉所有客户端 JavaScript。

src/pages/index.astro
<MyReactComponent />

这听起来可能很严格,但正是这种做法使得 Astro 网站默认保持快速,并且避免开发者不小心发送不必要或不想要的 JavaScript,而拖慢他们的网站速度。

只需使用一个 client:* 指令,就可以将任何静态 UI 组件转变为交互式岛屿。然后 Astro 会自动构建并打包你的客户端 JavaScript,以优化性能。

src/pages/index.astro
<!-- 现在这个组件在页面上是可交互的了!
而网站的其他部分仍然是静态。 -->
<MyReactComponent client:load />

在使用群岛时,客户端的 JavaScript 只会加载你所使用 client:* 指令明确标记的交互组件。

并且由于交互是在组件层面配置的,所以你可以根据每个组件的使用情况来处理不同的加载优先级。例如,client:idle 告诉一个组件在浏览器变为空闲时加载,而 client:visible 告诉一个组件只有在进入视口后才加载。

客户端群岛的优势

Astro 群岛的最明显的好处就是性能:你网站的大部分区域都被转换为了快速、静态的 HTML,JavaScript 只有在需要的时候才会加载到各个组件中。JavaScript 是一个加载得最慢的资源。每一个字节都影响着阅读者的体验!

另一个好处是并行加载。在上面的一些假想例子中,重要性更低的图像轮播不应该阻挡更重要的页头部分的加载。它俩并行加载但独自激活(hydrate),这表明阅读者并不需要等着更沉重的图像轮播加载完毕就可以与页头交互了。

更棒的地方在于:你可以准确地告诉 Astro 如何以及何时渲染每个组件。如果该图像轮播的加载成本真的很高,你可以附加一个特殊的客户端指令,告诉 Astro 仅在轮播在页面上可见时才加载它。如果用户从未看到它,它永远不会被加载。

在 Astro 中,作为开发人员,你可以明确告诉 Astro 你的页面上的哪些组件也需要在客户端浏览器中运行。Astro 只会准确地补充页面上需要交互性的内容,并将你的网站的其余部分保留为静态 HTML。

群岛正是 Astro 在默认情况下能够如此迅速之秘诀!

服务器群岛是一种将昂贵或缓慢的服务器端代码移出主渲染进程的方法,通过这种方法可以轻松地将高性能静态 HTML 和动态服务器生成的组件结合起来。

server:defer 指令 添加到页面上的任何 Astro 组件,来将其变成自己的服务器岛屿:

src/pages/index.astro
---
import Avatar from '../components/Avatar.astro';
---
<Avatar server:defer />

该指令会将你的页面分解为较小的服务器渲染内容区域,每个区域并行加载。

你的页面的主要内容可以使用占位符内容(例如通用头像)立即完成渲染,直到岛屿自己的内容可用。对于服务器群岛,拥有个性化内容的小组件不会延迟静态页面的渲染。

这种渲染模式是为了便于移植而构建的。它不依赖于服务器的任何基础架构,因此它可以与任何主机配合使用,从 Docker 容器中的 Node.js 服务器到你所选择的无服务器供应商。

服务器群岛的优势

服务器群岛的优势之一是能够动态渲染页面的高度动态部分。它允许更积极地缓存外壳和主要内容,从而提供更快的性能。

另一个优势是提供出色的访客体验。服务器群岛经过了优化且加载速度快,通常情况下甚至在浏览器绘制页面之前即可完成。但在渲染岛屿所用的那短短的一段时间内,你可以展示自定义的回退内容,从而防止发生任何布局偏移。

受益于 Astro 服务器群岛的一个很好的例子是电子商务店面的网站。尽管产品页面的主要内容很少更改,但这些页面通常包含一些动态部分:

  • 标题中的用户头像。
  • 商品的特惠、特价信息。
  • 用户评价。

为这些元素使用服务器群岛,访客将能够立即看到页面最重要的部分,即产品。在个性化的部分可用之前,通用头像、旋转的加载进度和商店公告可以作为回退的内容用以显示。

详细了解如何在你的项目中使用服务器群岛 (EN)
贡献

你有什么想法?

社区
京ICP备15031610号-99