Astro 4.12:服务器岛屿

作者
Erika
Matthew Phillips

Astro 4.12 现已发布!此版本包含服务器岛屿的首次实验性发布,这是我们整合高性能静态 HTML 和动态服务器生成组件的新解决方案。此外还包括分页和语法高亮方面的改进。

此版本包括以下亮点

要升级现有项目,请使用自动化的 @astrojs/upgrade CLI 工具。或者,通过运行包管理器的升级命令来手动升级

# Recommended:
npx @astrojs/upgrade
# Manual:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

实验性功能:服务器岛屿

2021年,Astro 将“岛屿架构”理念引入主流,允许您创建交互式客户端组件的“岛屿”,同时页面的大部分内容是静态生成的。

通过服务器岛屿,我们将相同的架构扩展到了服务器端。服务器岛屿使得高性能静态 HTML 和动态服务器生成组件的结合变得容易。

在任何给定的网页中,您可能会有以下内容:

  • 完全静态且永不改变的内容。
  • 由数据库动态支持,变化不频繁,但比您部署的频率更高。
  • 个性化内容,为个人用户量身定制。

目前,您必须为所有这些类型的内容选择一种缓存策略,如果页面是登录体验,通常意味着根本没有缓存。现在,有了服务器岛屿,您可以鱼与熊掌兼得。

A diagram showing the server island population parts of the page from the server.

服务器岛屿用于您最动态的内容;例如用户的头像、购物车和产品评论等个性化内容。当这些组件被延迟加载时,您可以更积极地缓存页面本身。

这意味着无论用户是否登录,都将立即看到页面的最关键部分,因为它们正在边缘 CDN 上缓存。回退内容将在动态岛屿加载之前短暂可见。

每个岛屿都是独立于其他岛屿加载的;这意味着一个较慢的岛屿,例如连接到旧版后端的岛屿,不会延迟其他个性化内容的显示和交互。

性能

为了验证这一想法的可行性,我们构建了 server-islands.com。这个演示受到了 Next.js 部分预渲染演示的启发,并重新设计以符合 Astro 的风格。服务器岛屿与部分预渲染 (PPR) 有很多共同之处,尤其是在提高页面可缓存性这一目标上。

衡量指标partialprerendering.comserver-islands.com
TTFB0.838秒0.766秒
FCP1.740秒1.251秒
LCP1.740秒1.405秒
TBT0.093秒0.018秒
来源WebPageTestWebPageTest

server-islands.com 在重复运行中表现出持续更快的速度;它在最大内容绘制(Largest Contentful Paint)方面快了20%,这是 Google 的三大核心网页指标之一,影响着用户体验和搜索引擎优化。

服务器岛屿不像 PPR 那样在服务器上启动对源站的请求,而是从浏览器端执行。这意味着虽然服务器岛屿可以更早地绘制内容,但它们可能比 PPR 更晚完成。

服务器岛屿和 PPR 都最适用于主页内容可以进行边缘缓存的网站。它们适用于电子商务网站,但可能不适合用于社交网络动态。由于页面经过边缘缓存,对岛屿请求的等待时间是最小的。

最终,我们相信这种权衡是 Astro 用户在用户体验和通过核心网页指标方面获得最佳整体性能的方式,并且无需任何特殊的后端基础设施或支持即可开始使用。

可移植性

我们在构建服务器岛屿时考虑到了可移植性。它不依赖于任何服务器基础设施,因此可以与您拥有的任何主机配合使用,无论是 Docker 容器中的 Node.js 服务器,还是您选择的无服务器提供商。

我们的实现主要发生在构建时,组件内容会被替换为一个小脚本,其大小几乎可以发布一条推文。

每个标记有 server:defer 的岛屿都被拆分成独立的特殊路由,脚本在运行时会抓取它们。权衡之处在于,如果岛屿依赖于边缘处理,它可能无法获得先发渲染优势,但我们认为迄今为止所采取的更简单方法在性能数据上更具优势。

试用服务器岛屿

我们仍在努力完善该功能,但您今天就可以通过在 Astro 4.12 中启用该功能来试用 Astro 服务器岛屿。

import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'hybrid',
adapter: netlify(),
experimental: {
serverIslands: true,
},
})

顾名思义,服务器岛屿在服务器上运行,因此您需要使用 'server''hybrid' 输出模式。启用此功能后,您可以在任何组件上使用 server:defer 指令来使用它们。

<Avatar server:defer>
<GenericUserImage slot="fallback" />
</Avatar>

当 Astro 构建您的站点时,它将省略该组件并在其位置注入一个脚本,此外还包括您标记为 slot="fallback" 的内容。当页面在浏览器中加载时,这些组件及其传递的任何 props 都将请求到一个特殊的端点,该端点会渲染它们并返回 HTML。

服务器岛屿是普通的 Astro 组件,可以使用 Astro 中您期望的任何功能,例如中间件、插槽和 client: 岛屿。

参与其中

服务器岛屿有一个活跃的 RFC。我们仍在敲定细节和功能;例如,我们可能会添加加密属性。请在 4.12 版本中试用,并告诉我们您的想法。

在分页数据中添加了 firstlast URL

paginate() 辅助函数现在在分页数据中返回 firstlast 属性。这些属性分别包含第一页和最后一页的 URL。感谢 @tsawada 贡献此功能!

添加了对 Shiki 的 defaultColor 选项的支持

defaultColor 选项允许您覆盖主题内联样式的值,仅添加 CSS 变量,从而在应用多个颜色主题时提供更大的灵活性。此选项可以在您的 Shiki 配置中进行配置以应用于整个站点,也可以传递给 Astro 内置的 <Code> 组件来样式化单个代码块。感谢 @madcampos 贡献此功能!

新的 inferRemoteSize 函数

在 Astro 4.4 中,我们为 Image 和 Picture 组件以及 getImage() 添加了一个新属性,用于自动推断远程图片的大小。感谢 @itsmatteomanf,此版本现在包含一个新函数 inferRemoteSize(),允许您独立于这些组件或 getImage() 获取远程图片的大小。

如果您使用图片宽度生成不同的密度,或者您需要图片尺寸用于样式目的,这会很有用。

---
import { inferRemoteSize, Image } from 'astro:assets';
const { width, height } = await inferRemoteSize('https://...');
---
<Image src={"https://..."} width={width / 2} height={height} densities={[1.5, 2]} />

更多内容

一如既往,Astro 4.12 包含了更多本文未提及的 bug 修复和小型改进!查看完整的 发布说明以了解更多信息。

特别感谢 @sarah11918@Fryuni@ARipeAppleByYoursTruly 以及所有为本次发布做出贡献的人员。