跳转到内容

按需渲染

你的 Astro 项目代码必须经过渲染生成 HTML 才能在网页上显示。

默认情况下,Astro 的页面、路由和 API 端点会在构建时预先渲染为静态页面。但你可以选择让部分或全部路由在请求时由服务器进行按需渲染。

按需渲染的页面和路由会在每次访问时生成,并可为每个访客定制内容。例如,按需渲染的页面可以向已登录用户显示账户信息或展示实时更新的数据,而无需重新构建整个网站。

在请求时由服务端进行的按需渲染也被称为服务端渲染 (SSR)

要实现页面按需渲染,需要添加适配器。每个适配器允许 Astro 输出可在特定运行时环境运行的脚本(如 Netlify、Cloudflare),这些环境会在服务器上执行代码以响应请求生成页面。

即使你的站点完全静态且不需要按需渲染任何页面,也建议添加适配器。例如,Netlify 适配器可启用 Netlify 的图片 CDN,而服务端群岛 (EN)需要安装适配器才能在组件上使用 server:defer

SSR 适配器

Astro 为 Node.jsNetlifyVercelCloudflare 维护官方适配器。你可以在集成目录找到官方和社区适配器,选择与你部署环境匹配的适配器。

使用以下 astro add 命令可添加任何由 Astro 维护的官方适配器集成。该命令将自动安装适配器并修改 astro.config.mjs 文件。

例如,安装 Netlify 适配器可运行:

终端窗口
npx astro add netlify

你也可以手动安装 NPM 包(如 @astrojs/netlify)并自行修改 astro.config.mjs

注意不同适配器可能有不同的配置选项。请阅读各适配器文档,并在 astro.config.mjs 中为所选适配器应用必要的配置。

默认情况下,整个 Astro 站点将预先生成静态 HTML 页面。但你可以选择在需要服务端渲染的路由(如需要检查 cookie 显示个性化内容的页面)上禁用预渲染。

首先,添加适配器集成以在 Astro 项目中启用服务端按需渲染。

然后在需要按需渲染的页面或端点顶部添加 export const prerender = false,其余页面仍保持静态:

src/pages/page-rendered-on-demand.astro
---
export const prerender = false
---
<html>
<!--
此内容将按需服务端渲染!
只需为服务器运行时添加适配器集成!
其他所有页面仍会在构建时静态生成!
-->
<html>

以下示例通过禁用预渲染,使端点每次被访问时生成随机数:

src/pages/randomnumber.js
export const prerender = false;
export async function GET() {
let number = Math.random();
return new Response(
JSON.stringify({
number,
message: `这是一个随机数:${number}`,
}),
);
}

对于高度动态(highly dynamic app)的应用,在添加适配器后,可以将构建输出配置设为 output: 'server'默认按需服务端渲染所有页面。这等同于在所有页面上禁用预渲染。

然后,你可以选择对不需要服务端执行的页面(如隐私政策、关于页面)启用预渲染:

src/pages/about-my-app.astro
---
export const prerender = true
---
<html>
<!--
配置了 `output: 'server'`,但此页面是静态的!
站点其余部分将按需渲染!
-->
<html>

通过向任意页面或路由添加 export const prerender = true 可预渲染静态页面或端点:

src/pages/myendpoint.js
export const prerender = true;
export async function GET() {
return new Response(
JSON.stringify({
message: `这是静态端点`,
}),
);
}
查看配置参考中关于 output 设置的更多信息。

通过 HTML 流式传输,文档会被拆分为多个片段按顺序发送,并在浏览器中按序渲染。Astro 在按需渲染中使用此技术,逐个组件发送到浏览器。这能确保用户尽快看到内容,但网络状况可能导致大文档加载缓慢,数据获取也可能阻塞页面渲染。

按需渲染的页面或 API 端点可以检查、设置、获取和删除 cookie。

以下示例更新页面访问计数器的 cookie 值:

src/pages/index.astro
---
export const prerender = false; // 'server' 模式下无需此设置
let counter = 0
if (Astro.cookies.has('counter')) {
const cookie = Astro.cookies.get('counter')
const value = cookie?.number()
if (value !== undefined && !isNaN(value)) counter = value + 1
}
Astro.cookies.set('counter', String(counter))
---
<html>
<h1>计数器 = {counter}</h1>
</html>

更多关于 Astro.cookiesAstroCookie 类型的细节请参阅 API 参考。

Astro.response 是标准的 ResponseInit 对象,可用于设置响应状态和标头。

以下示例在产品不存在时为产品页面设置响应状态和状态文本:

src/pages/product/[id].astro
---
export const prerender = false; // 'server' 模式下无需此设置
import { getProduct } from '../api';
const product = await getProduct(Astro.params.id);
// 未找到产品
if (!product) {
Astro.response.status = 404;
Astro.response.statusText = 'Not found';
}
---
<html>
<!-- 页面内容... -->
</html>

可以通过 Astro.response.headers 对象设置响应头:

src/pages/index.astro
---
export const prerender = false; // 'server' 模式下无需此设置
Astro.response.headers.set('Cache-Control', 'public, max-age=3600');
---
<html>
<!-- 页面内容... -->
</html>

在按需渲染的页面中,可以直接返回 Response 对象,或使用 Astro.redirect 进行重定向。

以下示例在动态页面中查找数据库中的 ID,如果产品不存在则返回 404,如果产品不再可用则重定向用户到其他页面,或者显示产品信息:

src/pages/product/[id].astro
---
export const prerender = false; // 'server' 模式下无需此设置
import { getProduct } from '../api';
const product = await getProduct(Astro.params.id);
// 未找到产品
if (!product) {
return new Response(null, {
status: 404,
statusText: '未找到'
});
}
// 产品不再可用
if (!product.isAvailable) {
return Astro.redirect("/products", 301);
}
---
<html>
<!-- 页面内容... -->
</html>

Astro.request 是标准的 Request 对象,可用于获取 urlheadersmethod 甚至请求的 body

在非静态生成的页面中,可以通过该对象获取额外信息。

请求标头可通过 Astro.request.headers 获取,其行为与浏览器的 Request.headers 一致。这是一个 Headers 对象,可用来获取 cookie 等标头信息。

src/pages/index.astro
---
export const prerender = false; // 'server' 模式下无需此设置
const cookie = Astro.request.headers.get('cookie');
// ...
---
<html>
<!-- 页面内容... -->
</html>

请求的 HTTP 方法可通过 Astro.request.method 获取,其行为与浏览器的 Request.method 一致。它返回请求中使用的 HTTP 方法的字符串表示。

src/pages/index.astro
---
export const prerender = false; // 'server' 模式下无需此设置
console.log(Astro.request.method) // GET(浏览器访问时)
---

更多关于 Astro.request 的细节请参阅 API 参考。

服务器端点(也称 API 路由)是位于 src/pages/ 目录下 .js.ts 文件中导出的特殊函数。作为服务端按需渲染的强大特性,API 路由能安全地在服务端执行代码。

该函数接收端点上下文并返回 Response 对象。

更多信息请参阅端点指南

贡献 社区 赞助
京ICP备15031610号-99