服务器群岛

服务器群岛允许你单独按需渲染动态或个性化的 “群岛”,且无需牺牲页面其他部分的性能。

这意味着你的访客将更快地看到你页面最重要的部分,并允许你的主要内容被更积极地缓存,从而提供更快的性能。

服务器群岛组件

服务器孤岛是一个普通的服务器渲染的 Astro 组件,它被指定为延迟渲染,直到其内容可用。

你的页面将立即使用任何指定的 回退内容作为占位 来渲染。然后,在客户端上获取组件自己的内容,并在可用时显示。

安装 适配器 来执行延迟渲染后,将 ‘server:defer’ 指令 添加到页面上的任意组件,来将其变成组件自己的岛屿:

src/pages/index.astro

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

这些组件可以使用适配器执行 你在按需渲染页面中通常执行的任何操作,例如获取内容和访问 cookie:

src/components/Avatar.astro

---
import { getUserAvatar } from '../sessions';
const userSession = Astro.cookies.get('session');
const avatarURL = await getUserAvatar(userSession);
---
<img alt="User avatar" src={avatarURL} />

向服务器群岛组件传递 Props

传递给服务器群岛组件的属性必须 序列化:转换为适合在网络传输或存储的格式。然而,Astro 并不能序列化所有类型的数据结构。因此,在将属性传递给服务器群岛组件时,存在一些限制。

以下是支持的属性类型:普通对象、number、string、Array、Map、Set、RegExp、Date、BigInt、URL、Uint8Array、Uint16Array、Uint32Array 和 Infinity

需要注意的是,函数不能传递给带有 server:defer 标记的组件,因为它们不能被序列化。具有循环引用的对象也不能被序列化。

服务器群岛回退内容

当在组件上使用 server:defer 属性来延迟其渲染时,你可以在默认的载入内容中插入包含 "fallback" 的 “slot”。

你的回退内容最初将在页面加载时与页面的其余部分一起渲染,并在可用时替换为组件的内容。

要添加回退内容,请在传递给服务器岛屿组件的子组件(其他组件或 HTML 元素)上添加 slot="fallback":

---
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
  <GenericAvatar slot="fallback" />
</Avatar>

此回退内容可以是:

• 一个通用头像,用以代替用户自己的头像。

• 占位符 UI,例如自定义消息。

• 加载进度提示,例如旋转加载样式。

工作原理

服务器孤岛的实现主要发生在构建时,那时组件内容会被转换成一个小脚本。

每个被标记上 server:defer 的孤岛都被拆分为自己的特殊路由,脚本在运行时会获取该路由。当 Astro 构建你的网站时,它会略过该组件并在其位置注入一个脚本,以及你用 slot="fallback" 标记的任何内容。

当页面在浏览器中加载时,这些组件将被请求到一个特殊端点,该端点渲染这些组件并返回 HTML。这意味着用户将立即看到页面最关键的部分。而在加载动态群岛之前,回退内容将在短时间内可见。

每个岛屿都独立于其他岛屿进行加载。这意味着较慢的岛屿也不会拖累你其余个性化内容的加载。

此渲染模式旨在实现可移植性。它不依赖于任何服务器基础设施,因此它可以与你拥有的任何主机配合使用,从 Docker 容器中的 Node.js 服务器到你选择的无服务器提供商。

缓存

服务器群岛的数据是通过 GET 请求检索的,在 URL 查询中将 props 作为加密字符串传递。这允许使用标准的 Cache-Control 指令通过 Cache-Control HTTP 标头 来缓存数据。

但是,出于实际原因,浏览器将 URL 限制为最大长度 2048 字节,以避免导致服务被拒绝的问题。如果你的查询字符串导致你的 URL 超过这个限制,Astro 将发送一个 POST 请求,其中包含正文中的所有 props。

浏览器不会缓存 POST 请求,因为它们是用于提交数据的,如果缓存则可能会导致数据完整性或安全问题。因此,项目中的任何现有缓存逻辑都将中断,尽可能只将必要的 props 传递给你的服务器群岛,而避免发送整个数据对象和数组,以保持你的查询字符串足够小。

访问服务器岛屿中的页面 URL

在大多数情况下,你的服务器岛屿组件可以通过 传递 props 来获取有关渲染它的页面的信息,就像在普通组件中一样。

但是,服务器群岛是在页面请求之外的、自己的隔离上下文中运行的。服务器岛屿组件中的 Astro.url 和 Astro.request.url 都会返回一个结构看起来像 /_server-islands/Avatar 的 URL,而不是浏览器中当前页面的 URL。此外,如果你正在预渲染页面,你将无法访问 query 参数等信息,以便其作为 props 传递。

要从页面的 URL 访问信息,你可以检查 Referer 标头,其中将会包含:在浏览器中加载该岛屿的页面的地址:

---
const referer = Astro.request.headers.get('Referer');
const url = new URL(referer);
const productId = url.searchParams.get('product');
---

复用加密密钥

Astro 使用 加密技术 来加密传入到服务器群岛的 prop,防止敏感数据意外泄露。该加密机制依赖于每次构建时生成的随机密钥,该密钥会嵌入到服务端包中。

大多数部署托管平台会自动保持前端与后端的同步。但在滚动部署、多区域托管、缓存含服务端岛屿页面的 CDN 这些场景中,你可能需要使用固定的加密密钥。

在滚动部署(例如:Kubernetes)的环境中,前端资源(负责加密 prop)和后端函数(负责解密 prop)可能会临时使用不同的密钥,又或者是 CDN 可能仍在分发用旧密钥构建的页面,导致传递给服务端岛屿的加密 prop 无法被解密。

在这些情况下,使用 Astro CLI 生成可复用的加密密钥,并在构建环境中,设置你的环境变量:

astro create-key

将该值配置到 ASTRO_KEY 环境变量中(如在 .env 文件中)并包含在 CI/CD 或主机的构建设置中。这能确保构建时始终使用同一密钥,保持加密与解密同步。

来源:Astro 文档团队:服务器群岛;正文采用官方已有中文内容,未声明为原创或自行翻译,仅转换排版、将内部链接解析为原站绝对地址。代码取自对应官方文档源文件并保留原样。依据文档仓库 MIT 许可保留以下完整声明:

MIT License

Copyright (c) 2022 withastro

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容