3078 字
15 分钟

Astro SSR配置完全指南:3步启用服务端渲染

Astro博客跑得飞快,Lighthouse评分95+,突然老板说”咱们加个用户登录功能吧”。这下傻眼了,静态站点怎么搞用户登录?去翻官方文档,什么SSR、SSG、Hybrid、adapter一堆概念扑面而来,越看越晕。

其实配置Astro SSR没你想的那么复杂。这篇文章会带你搞清楚:什么时候必须用SSR,怎么快速配置各种适配器,以及如何在一个项目里同时用SSR和SSG。

什么时候你需要SSR而不是SSG?#

最简单的判断标准:内容是构建时就确定的,还是每次访问都可能变?

SSG(Static Site Generation)就像餐厅提前备好的套餐,早上厨师把菜做好了,客人来了直接端上桌。博客文章、产品介绍页、关于我们,这些内容基本不变,用SSG完美。

SSR(Server-Side Rendering)就像现点现做,客人点完单,厨师根据你的需求现场炒菜。用户登录后看到的”欢迎回来,张三”,实时股票价格,购物车里的商品数量,这些每个人看到的都不一样,必须用SSR。

看看下面这5个场景,中一个就得考虑SSR了:

1. 用户认证和个性化内容

最典型的例子就是登录。你不可能在构建时就知道谁会登录,显示什么用户名。

2. 实时数据展示

天气预报、股票行情、体育比赛分数。这些数据每分钟都在变,你总不能每分钟构建一次网站吧?用SSR,每次用户访问都去拉最新数据。

3. 数据库查询

电商网站的商品搜索,每个关键词的搜索结果都不一样,不可能提前生成所有可能的搜索结果页面。

4. API路由

表单提交、文件上传、第三方API调用,这些都需要后端逻辑。Astro的SSR模式支持创建API路由(src/pages/api/xxx.js),让你不用单独搭后端服务器。

5. A/B测试和个性化推荐

根据用户地理位置、访问时间、历史行为展示不同内容。

博客文章详情页能SSR吗?能,但没必要。文章内容是固定的,SSG生成静态HTML,直接走CDN,访问速度更快,服务器成本更低。

Hybrid模式:鱼和熊掌兼得

Astro 2.0引入的Hybrid模式,让你在一个项目里,静态页面用SSG,动态页面用SSR。比如一个电商网站:

  • 首页、About页、帮助文档 → SSG
  • 登录页、用户中心、购物车 → SSR
  • 商品详情页 → SSG
  • 搜索结果页 → SSR

我有个朋友的博客就是这么搞的,文章列表和详情用SSG,评论区用SSR,Lighthouse评分还是保持在95+。

快速上手 - 3步启用SSR模式#

确定项目需要SSR之后,开始配置。先用Node.js适配器演示,这是最通用的方案。

第一步:一键安装适配器

Astro官方提供了自动配置命令,直接在项目根目录运行:

npx astro add node

这一条命令会自动帮你做三件事:

  1. 安装 @astrojs/node
  2. 修改 astro.config.mjs 配置文件
  3. 更新 package.json 的依赖

如果你想手动安装,也可以这样:

npm install @astrojs/node

然后手动修改配置文件。

第二步:修改配置文件

打开项目根目录的 astro.config.mjs

astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server', // 开启SSR模式
adapter: node({
mode: 'standalone' // 独立服务器模式
}),
});

output配置

  • 'static'(默认):所有页面SSG,输出纯静态HTML
  • 'server':所有页面SSR,每次请求都动态生成
  • 'hybrid':默认SSG,可以按页面开启SSR(推荐)

mode配置

  • 'standalone':Astro启动独立的Node.js服务器
  • 'middleware':生成中间件,可以集成到Express、Koa等框架

我一般用 standalone,因为Astro自带的服务器已经够用了。如果你的项目本来就有Express后端,想把Astro作为一部分,那就用 middleware

第三步:构建和运行

配置完成,构建项目:

npm run build

构建完成后,dist/ 目录下多了个 server/ 文件夹,里面有个 entry.mjs 文件,这就是SSR服务器的入口。

运行SSR服务器:

node ./dist/server/entry.mjs

默认会在 http://localhost:4321 启动服务。

开发环境调试

开发时不用每次都构建,直接用:

npm run dev

开发服务器会自动支持SSR,修改代码实时生效。

常见问题排查

  1. 端口被占用:设置环境变量 PORT=3000 node ./dist/server/entry.mjs
  2. 找不到adapter模块:确认 @astrojs/node 已经安装,运行 npm install
  3. 页面404:检查 src/pages/ 目录下的文件是否正确

配置SSR真的就这么简单。我第一次配的时候,从开始到运行成功,不到5分钟。

主流适配器配置详解#

如果你的项目托管在Vercel、Netlify或Cloudflare,配置SSR会更简单。这些平台都有Astro官方维护的专用适配器。

Vercel适配器 - Serverless函数的王者

Vercel是我最常用的部署平台:

npx astro add vercel

配置文件:

astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server',
adapter: vercel(),
});

Vercel的特色功能:ISR(增量静态再生)

这是Vercel独有的功能,可以让你的SSR页面像SSG一样快。

adapter: vercel({
isr: {
expiration: 60, // 缓存60秒
},
}),

Vercel部署流程

  1. 配置好适配器
  2. 推送代码到GitHub
  3. 在Vercel控制台导入项目
  4. 构建命令:npm run build
  5. 点击部署

Netlify适配器 - Edge Functions的高手

npx astro add netlify

配置文件:

astro.config.mjs
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'server',
adapter: netlify({
edgeMiddleware: true,
}),
});

把中间件逻辑(比如身份验证、重定向)运行在边缘节点,响应更快。

Netlify的重定向配置

在项目根目录创建 _redirects 文件:

/old-page /new-page 301

Cloudflare适配器 - 全球CDN加速

npx astro add cloudflare

配置文件:

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});

Cloudflare Workers运行在全球300+数据中心,延迟极低。

需要注意的是,Cloudflare Workers的运行环境和Node.js不完全一样,有些Node.js的API用不了(比如 fs 文件系统)。

适配器对比表

适配器适用场景核心优势主要限制
Node.js自建服务器、VPS完全控制,无限制需自行运维,成本高
Vercel个人项目、小团队零配置,ISR支持免费额度有限
Netlify静态站+动态功能Edge Functions快构建时长限制
Cloudflare全球用户,低延迟边缘计算,价格低Workers环境限制

Hybrid混合渲染实战#

前面讲了纯SSR的配置,现在到重点了:Hybrid模式。这是Astro的杀手锏,让你在一个项目里同时享受SSG的速度和SSR的灵活性。

配置Hybrid模式

只需把 output 改成 'hybrid'

astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'hybrid', // 默认SSG,按需SSR
adapter: node(),
});

默认所有页面都是SSG,然后你可以在需要SSR的页面上加一行代码,开启SSR。

页面级别控制渲染方式

在页面文件的frontmatter里加一行:

// src/pages/dashboard.astro(SSR)
---
export const prerender = false; // 关闭预渲染,改用SSR
const user = Astro.cookies.get('user');
---
<h1>欢迎回来,{user?.name}</h1>
<p>你有 {user?.notifications} 条未读消息</p>

prerender = false 意思是”别在构建时生成,等用户访问时再动态生成”。

反过来,如果你把 output 设成 'server'(全部SSR),想让某个页面用SSG:

// src/pages/about.astro(SSG)
---
export const prerender = true; // 强制在构建时生成
---
<h1>关于我们</h1>
<p>这个页面内容不变,提前生成好,访问超快。</p>

重点总结

output配置默认行为如何改变个别页面
'hybrid'所有页面SSGexport const prerender = false → 该页面SSR
'server'所有页面SSRexport const prerender = true → 该页面SSG

我一开始总是搞反,后来记住了:hybrid是SSG优先,server是SSR优先

实战案例:博客+用户系统

假设你在做一个博客平台,有文章展示和用户登录功能。

项目结构

src/pages/
├── index.astro // 首页(SSG)
├── about.astro // 关于页(SSG)
├── blog/
│ ├── [slug].astro // 文章详情(SSG)
│ └── index.astro // 文章列表(SSG)
├── login.astro // 登录页(SSR)
├── dashboard.astro // 用户中心(SSR)
└── api/
└── comments.js // 评论接口(SSR)

配置文件

astro.config.mjs
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
});

静态页面(不需要特殊配置)

src/pages/blog/[slug].astro
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
---
<article>
<h1>{post.data.title}</h1>
<div set:html={post.body} />
</article>

动态页面(需要SSR)

src/pages/dashboard.astro
---
export const prerender = false;
const token = Astro.cookies.get('token')?.value;
if (!token) {
return Astro.redirect('/login');
}
const user = await fetch(`https://api.example.com/user`, {
headers: { Authorization: `Bearer ${token}` }
}).then(res => res.json());
---
<div>
<h1>欢迎,{user.name}</h1>
<p>邮箱:{user.email}</p>
<p>上次登录:{user.lastLogin}</p>
</div>

API路由(自动SSR)

src/pages/api/comments.js
export async function POST({ request }) {
const { articleId, content } = await request.json();
await db.comments.insert({
articleId,
content,
createdAt: new Date(),
});
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
}
export async function GET({ url }) {
const articleId = url.searchParams.get('articleId');
const comments = await db.comments.findMany({
where: { articleId },
orderBy: { createdAt: 'desc' }
});
return new Response(JSON.stringify(comments), {
headers: { 'Content-Type': 'application/json' }
});
}

这样配置的好处

  1. 静态页面依然快如闪电,Lighthouse评分95+
  2. 动态页面实时获取数据
  3. API路由提供后端能力
  4. 构建时间短

我之前做的一个项目,50篇博客文章+用户系统,构建时间才20秒,部署后静态页面秒开,动态页面响应也在100ms以内。

常见问题与最佳实践#

配置SSR的过程中,我踩过不少坑。

问题1:报错 Astro.clientAddress is only available when using output: 'server'

原因:你在代码里用了 Astro.clientAddress,但配置文件里 output 还是 'static'

解决方案

astro.config.mjs
export default defineConfig({
output: 'server', // 或 'hybrid'
adapter: node(),
});

Astro.clientAddressAstro.cookiesAstro.redirect() 这些动态API,只能在SSR模式下用。

问题2:部署后页面404,本地开发正常

原因:适配器配置不对,或者部署平台的构建命令/输出目录设置错误。

解决方案

Vercel部署

  • 构建命令:npm run build
  • 输出目录:.vercel/output

Netlify部署

  • 构建命令:npm run build
  • 发布目录:dist.netlify

问题3:SSR页面加载很慢,超过2秒

原因:服务器性能不足,或者数据库查询太慢。

解决方案

  1. 使用缓存
  2. 优化数据库查询:加索引、减少JOIN
  3. 考虑ISR(如果用Vercel)

问题4:环境变量在客户端获取不到

原因:Astro的环境变量有客户端和服务端之分。

解决方案

服务端用:

const secret = import.meta.env.SECRET_KEY;

客户端用:

const apiUrl = import.meta.env.PUBLIC_API_URL; // 必须以PUBLIC_开头

最佳实践总结

  1. 默认用Hybrid模式:除非所有页面都需要SSR,否则 output: 'hybrid' 是最优选择
  2. 按需启用SSR:只对真正需要动态渲染的页面设置 prerender = false
  3. 静态资源走CDN:图片、CSS、JS文件放在 public/ 目录
  4. 缓存策略:对不常变的动态内容用缓存或ISR
  5. 环境变量分离:敏感信息用服务端环境变量,公开配置用 PUBLIC_ 前缀
  6. 监控性能:用Vercel Analytics或Google Analytics监控SSR页面的响应时间

结论#

核心就三句话:

1. SSR不是万能的,按需使用才是王道

静态页面用SSG,动态页面用SSR,大部分项目用Hybrid模式最合适。我见过有人把整个博客都改成SSR,结果性能反而下降了。

2. 适配器选择看部署平台,配置其实很简单

如果用Vercel/Netlify/Cloudflare,一行 npx astro add [platform] 就搞定。如果自建服务器,npx astro add node 也就5分钟的事。

3. Hybrid模式让你鱼和熊掌兼得

这才是Astro的精髓。静态页面保持95+ Lighthouse评分,动态页面实现个性化功能。

下一步行动

  1. 马上试一试:打开你的Astro项目,运行 npx astro add node
  2. 思考自己的需求:列出项目里哪些页面需要动态渲染
  3. 深入学习:Astro最近推出的Server Islands功能,可以让SSG页面里嵌入SSR组件

不要过度优化。如果你的网站访问量不大(日PV<1万),其实静态站点就够用了,没必要上SSR增加复杂度。技术选型要服务业务。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
Astro SSR配置完全指南:3步启用服务端渲染
https://blog.moewah.com/posts/astro-ssr-setup-complete-guide-three-step-enable-server-side-rendering/
作者
GoWah
发布于
2025-04-05
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
GoWah
Hello, I'm GoWah.
分类
标签
站点统计
文章
160
分类
9
标签
350
总字数
301,106
运行时长
0
最后活动
0 天前

目录