预渲染
预渲染(Prerendering)是在构建时生成静态 HTML 页面,而不是在用户请求时动态渲染。预渲染的页面可以部署到任何静态托管,无需 Node.js 服务器。
预渲染 vs SSR vs SSG
| 特性 | 预渲染(Prerender) | SSR | SSG |
|---|---|---|---|
| 渲染时机 | 构建时 | 请求时 | 构建时(全量) |
| 服务器需求 | 无(纯静态) | Node.js 服务器 | 无(纯静态) |
| 内容更新 | 需要重新构建 | 实时 | 需要重新构建 |
| 性能 | 最快(静态文件) | 中等 | 最快(静态文件) |
| 适用场景 | 静态页面 | 动态内容 | 博客、文档 |
预渲染 vs SSG
- 预渲染:选择性渲染部分页面(Nuxt 的默认方式)
- SSG(静态站点生成):渲染所有页面
- Nuxt 4 中,
nuxt generate+prerender配置 = SSG
Nuxt 4 的混合渲染
你可以在同一个项目中,对不同的路由使用不同的渲染模式——部分预渲染、部分 SSR、部分 CSR。
routeRules 配置
通过 routeRules 配置哪些页面需要预渲染:
export default defineNuxtConfig({
routeRules: {
// 预渲染指定页面
'/': { prerender: true },
'/about': { prerender: true },
'/pricing': { prerender: true },
// 预渲染特定动态路由
'/blog/post-1': { prerender: true },
'/blog/post-2': { prerender: true },
},
})prerender: true 的效果
构建时访问该页面,生成静态 HTML 文件。后续访问直接返回静态文件,不再执行服务端渲染。
Nitro 预渲染配置
更详细的预渲染配置在 nitro.prerender 中:
export default defineNuxtConfig({
nitro: {
prerender: {
// 预渲染路由列表
routes: ['/', '/about', '/pricing'],
// 自动爬取链接(发现页面中的内部链接,自动预渲染)
crawlLinks: true,
// 忽略路由(不预渲染)
ignore: [
'/admin/**', // 管理后台不需要预渲染
'/api/**', // API 不需要预渲染
'/dashboard', // 需要登录的页面
],
// 并发数(构建时同时渲染的页面数)
concurrency: 10,
},
},
})crawlLinks: true 的原理
- 渲染
routes中指定的页面 - 解析页面中的所有
<a href="...">链接 - 如果链接指向同站页面,自动加入预渲染队列
- 递归爬取,直到没有新页面
INFO
️ crawlLinks 可能导致构建时间过长:如果网站有大量页面 建议配合 ignore 排除不需要预渲染的页面
动态路由预渲染
动态路由(如 /blog/[id])默认不会被预渲染——因为构建时不知道有哪些具体的 ID。需要手动指定:
方式 1:列出所有路由
export default defineNuxtConfig({
nitro: {
prerender: {
routes: [
'/',
'/blog',
'/blog/1',
'/blog/2',
'/blog/3',
],
},
},
})方式 2:从 API 获取路由列表(推荐)
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
async 'nitro:config'(nitroConfig) {
// 从 API 获取所有博客文章 ID
const posts = await $fetch('https://api.example.com/posts')
const routes = posts.map(post => `/blog/${post.id}`)
// 添加到预渲染列表
nitroConfig.prerender?.routes?.push(...routes)
},
},
})nitro:config 钩子
在 Nitro 配置生成后、构建开始前执行。可以动态修改预渲染列表。
方式 3:使用 prerenderRoutes
在页面中声明预渲染的路由:
<script setup>
// 预渲染相关页面
prerenderRoutes(['/blog/1', '/blog/2'])
</script>prerenderRoutes 的原理
在当前页面预渲染时,将指定路由加入预渲染队列。适合在列表页中自动预渲染详情页。
预渲染 + 缓存策略(SWR/ISR)
预渲染配合缓存策略,实现静态内容 + 定时更新的混合模式:
SWR(Stale-While-Revalidate)
export default defineNuxtConfig({
routeRules: {
// 首页:预渲染 + 缓存 1 小时
'/': { prerender: true, swr: 3600 },
// 博客列表:ISR(60 秒后重新验证)
'/blog/**': { isr: 60 },
// 文档页面:预渲染 + 缓存 24 小时
'/docs/**': { prerender: true, swr: 86400 },
// API:不预渲染
'/api/**': { cors: true },
},
})SWR vs ISR
| 策略 | 行为 | 适用场景 |
|---|---|---|
swr: 3600 | 返回缓存(最多 1 小时),后台刷新 | 内容更新不频繁 |
isr: 60 | 返回缓存,60 秒后标记为过期,下次请求时刷新 | 内容定期更新 |
isr: true | 返回缓存,直到手动清除 | 手动控制更新 |
ISR(Incremental Static Regeneration)
export default defineNuxtConfig({
routeRules: {
// 博客文章:ISR 5 分钟
'/blog/**': { isr: 300 },
},
})ISR 的工作流程:
1. 首次请求 → 渲染页面 → 缓存 → 返回
2. 5 分钟内请求 → 直接返回缓存(快!)
3. 5 分钟后首次请求 → 返回旧缓存 + 后台重新渲染
4. 下次请求 → 返回新缓存ISR 需要 Node.js 服务器或支持缓存的平台
纯静态部署(如 GitHub Pages)不支持 ISR。
ISR 支持的平台
Node.js、Vercel、Cloudflare、Netlify 等。
静态站点生成(SSG)
如果要生成完全的静态站点(所有页面预渲染):
export default defineNuxtConfig({
nitro: {
prerender: {
crawlLinks: true, // 自动爬取所有链接
},
},
})npx nuxt generate输出到 .output/public/,可以直接部署到任何静态托管。
SSG 的优缺点
| 优点 | 缺点 |
|---|---|
| 最快的加载速度 | 内容更新需要重新构建 |
| 无需服务器 | 动态路由需要手动指定 |
| 可部署到 CDN | 构建时间长(页面多时) |
| 安全性高(无服务端) | 无法处理用户特定的内容 |
混合渲染模式
Nuxt 4 支持在同一项目中混合使用不同的渲染模式:
export default defineNuxtConfig({
routeRules: {
// 静态页面:预渲染
'/': { prerender: true },
'/about': { prerender: true },
'/pricing': { prerender: true },
// 博客:ISR
'/blog/**': { isr: 300 },
// 管理后台:仅客户端渲染
'/admin/**': { ssr: false },
// API:标准 SSR
'/api/**': { cors: true },
// 重定向
'/old-path': { redirect: '/new-path' },
},
})混合渲染的优势
- 首页和营销页面预渲染 → 最快加载
- 博客等动态内容用 ISR → 自动更新
- 管理后台用 CSR → 无需 SSR
- 同一个项目,不同路由不同策略
部署预渲染站点
# 生成静态文件
npx nuxt generate
# 预览
npx nuxt preview
# 部署 .output/public/ 到静态托管
# - GitHub Pages
# - Netlify
# - Vercel
# - Cloudflare Pages
# - 阿里云 OSS + CDN
# - EdgeOne Pages选择部署平台
- 纯静态站点:GitHub Pages、Netlify、Cloudflare Pages
- 需要 ISR:Vercel、Node.js 服务器
- 中国用户:阿里云 OSS + CDN、EdgeOne Pages
知识脉络
API 路由 → 服务路由 → 服务中间件 → 服务插件 → 工具函数 → 事件处理 → 你在这里:预渲染
│
├─→ 相关:核心概念 → 渲染模式
│
└─→ 相关:部署上线 → 构建命令