首页 / Astro 教程 / 按需渲染(On-demand Rendering / SSR / 混合)

Astro 教程

按需渲染(On-demand Rendering / SSR / 混合)

本教程共 56 篇 · 第 36 篇 · 更新于 2026-08-07 · 约 10 分钟阅读

AstroAstro 教程按需渲染SSR混合模式output适配器

本节目标:搞懂 Astro 页面”什么时候生成”,以及 output: 'static' | 'server' | 'hybrid' 三种模式各自适合什么场景。

前面多章我们默认一个前提:页面在构建时一次性生成好,部署后访客直接看静态文件。但有些功能做不到——比如”显示当前登录用户的信息""每次刷新都给一个随机数""根据用户所在地区返回不同内容”。这些都需要页面在访客请求时才生成。这件事在 Astro 里叫按需渲染(On-demand Rendering),在业界也常叫 SSR(Server-Side Rendering,服务端渲染)

三种输出模式:output 配置

Astro 用 astro.config.mjs 里的 output 字段决定生成策略。它有三个值,这是 v7 的标准术语,务必记牢:

  • output: 'static':全部页面在构建时预渲染(prerender),产出纯静态 HTML。这是默认值,不需要适配器。
  • output: 'server':全部页面默认在请求时由服务器渲染(即整站 SSR)。
  • output: 'hybrid':混合模式。大部分页面仍静态预渲染,只有你标注”需要按需”的路由才在请求时渲染。
Note

旧教程里常见的 ssr: true 写法在 v4 之后已经废弃,请一律用 output 字段。这是本教程一律以 v7 文档为准的原因。看到老文章写 ssr:true,直接当成 output: 'server' 理解即可。

简单对比一下三种模式:

模式默认行为单个路由如何反转是否需要适配器
static全部静态某路由加 export const prerender = false 改为按需该路由按需时需要
hybrid全部静态某路由加 export const prerender = false 改为按需需要
server全部按需(SSR)某路由加 export const prerender = true 改回静态需要

可以看到,不管是哪种模式,控制”单个路由是否按需”的开关都是代码顶部的 export const prerender

适配器:让服务器能跑你的项目

只要你想让任何路由按需渲染,就必须安装一个适配器(adapter)。适配器的作用,是让 Astro 输出一段能在特定运行环境(runtime)上跑的脚本。运行环境就是”在服务器上真正执行代码、生成页面”的地方,比如 Netlify、Cloudflare、Vercel,或者普通 Node 服务器。

Astro 官方维护这些适配器:

  • @astrojs/node(Node.js 服务器)
  • @astrojs/vercel(Vercel)
  • @astrojs/netlify(Netlify)
  • @astrojs/cloudflare(Cloudflare)

安装最简单的方式是用 astro add 命令,它一步到位装好包并改好配置:

npx astro add netlify

你也能手动 npm install 对应包,再自己写 astro.config.mjs。不同适配器配置项不同,具体看各自文档。

Tip

即使你整站都是静态的,有时也值得装个适配器。比如 Netlify 适配器能开启图片 CDN;而**服务端岛屿(server island)**要用 server:defer 也必须装适配器。

单个路由改成按需渲染

假设你在 statichybrid 模式下,只有某一个页面需要按需渲染。给它加一行 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: `Here's a random number: ${number}`,
    })
  );
}

server 模式:整站 SSR

如果你做的是高度动态的站(比如带登录的后台),与其给每个页面都加 prerender = false,不如直接设 output: 'server',让所有页面默认按需渲染。这等价于”给每个页面都关掉预渲染”。

// astro.config.mjs
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';

export default defineConfig({
  output: 'server',
  adapter: netlify(),
});

之后,如果有个别页面(比如”关于我们""隐私政策”)不需要服务器、想做成静态,再单独加 prerender = true 即可:

---
// src/pages/about.astro
export const prerender = true
---
<html>
  <!-- output:'server' 已配置,但本页是静态的 -->
</html>

hybrid 模式:动静结合(推荐大多数场景)

hybrid 是实践中最常用的折中:站点默认静态、加载快、便宜;只有真正需要动态的路由才走服务器。写法上,它和 static 一样——默认静态,需要按需的路由加 prerender = false

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';

export default defineConfig({
  output: 'hybrid',
  adapter: vercel(),
});

选哪种?给你一个粗判:

  • 内容几天不变、追求极致加载速度 → static
  • 几乎每个页面都依赖登录态或实时数据 → server
  • 大部分是内容页、零星几个要动态 → hybrid
Note

无论 server 还是 hybrid,只要存在按需路由,就必须有适配器。纯 static 可以没有适配器。

容易混的一点:hybrid 和 server 的默认方向相反

新手常把 hybridserver 搞反,记住这句就清楚了:

  • hybrid:默认静态,你用 prerender = false 把个别路由”点亮”成按需。
  • server:默认按需,你用 prerender = true 把个别路由”关掉”回静态。

换句话说,单路由开关 prerender 的语义始终一致——false 就是按需,true 就是静态;变的是”全站默认值”由 output 决定。这样无论哪种模式,你写的 prerender 含义都不会变,不用在不同项目间反复改脑子。

Tip

拿不准用哪个,从 hybrid 起步最稳:绝大部分内容页保持静态、飞快;只有真正动态的少数路由标 prerender = false。等哪天发现几乎页页都要按需,再整体切到 server 也不迟。

按需渲染带来的新能力

页面在请求时由服务器生成,就能用上一批”构建时办不到”的能力。下面挑常用的说。

按需渲染的页面能读、写、删 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));
---

<h1>Counter = {counter}</h1>

响应状态与响应头

通过 Astro.response 能设置返回的状态码和响应头。比如商品不存在就返回 404:

---
export const prerender = false;
import { getProduct } from '../api';

const product = await getProduct(Astro.params.id);

if (!product) {
  Astro.response.status = 404;
  Astro.response.statusText = 'Not found';
}
---

<html></html>

设置缓存头也一样:

---
export const prerender = false;
Astro.response.headers.set('Cache-Control', 'public, max-age=3600');
---

<html></html>

读取请求信息

Astro.request 是个标准的请求对象,能拿到网址、请求头、请求方法,甚至请求体。常见用法是读请求头里的 Cookie:

---
export const prerender = false;
const cookie = Astro.request.headers.get('cookie');
---

<html></html>

HTML 流式渲染

按需渲染时,Astro 会一边渲染一边把 HTML 分块发给浏览器(流式渲染,HTML streaming)。用户能更早看到页面开头,不用等全部数据都取完。这对”页面要等好几个接口”的场景很友好。

小结

页面生成时机由 output 决定:static 全静态、server 全按需、hybrid 默认静态但可单路由按需。控制单个路由的开关是 export const prerender(按需就 false,静态就 true)。只要有用到按需渲染,就必须装适配器。按需渲染解锁了 Cookie、响应头、请求读取、流式渲染等能力,是做登录态、实时内容的基石。

下一章我们看中间件,它能在每次渲染前后统一”插手”请求与响应。