渲染模式
Nuxt 支持多种渲染模式,可以根据不同页面的需求灵活选择。理解渲染模式是理解 Nuxt 的关键——它直接决定了你的网站在 SEO、性能、用户体验上的表现。
为什么要关心渲染模式?
不同的渲染模式,用户体验完全不同:
| 你遇到的问题 | 可能是渲染模式选错了 |
|---|---|
| 搜索引擎搜不到我的网站 | 用了 CSR,爬虫看不到内容 |
| 用户打开页面看到白屏很久 | 没用 SSR,JS 要先下载完才能显示 |
| 后台管理系统不需要 SEO | 不需要 SSR,用 CSR 更轻量 |
| 服务器压力太大 | 可能需要 SSG 或缓存策略 |
一句话总结
渲染模式决定了"页面内容在哪里生成"——在服务器上(SSR)、在浏览器里(CSR)、还是构建时就生成好(SSG)。
通用渲染(SSR)
默认模式,页面在服务端渲染为 HTML,发送到客户端后再进行 Hydration。
工作流程
1. 用户请求 → 2. 服务端渲染 HTML → 3. 发送 HTML 到浏览器
↓
4. 页面显示 ← 5. Hydration(激活交互)逐步理解
- 用户请求:用户在浏览器输入 URL 或点击链接
- 服务端渲染:Nuxt 在服务器上执行 Vue 组件,生成完整的 HTML
- 发送 HTML:服务器把 HTML + JS + 数据(payload)发送给浏览器
- 页面显示:浏览器收到 HTML 后立即显示(用户已经能看到内容了)
- Hydration:浏览器下载 JS 后,把静态 HTML "激活"为可交互的 Vue 应用
为什么叫"Hydration"(水合)?
就像干海绵吸水后变得有弹性——静态 HTML(干海绵)加上 JavaScript(水),页面就变得可交互了。
优势
- ✅ 更快的首屏加载:用户看到 HTML 就有内容,不用等 JS
- ✅ 更好的 SEO:搜索引擎爬虫能抓取完整内容(不是空 HTML)
- ✅ 更好的无障碍支持:屏幕阅读器能读到内容
- ✅ 低性能设备也能快速显示:渲染在服务器完成,不消耗用户设备性能
配置
// nuxt.config.ts(默认就是 SSR,不写也行)
export default defineNuxtConfig({
ssr: true,
})大多数项目用 SSR 就对了
它是 Nuxt 的默认模式,也是 Nuxt 存在的意义——如果没有 SSR 需求,用 Vue 就够了。
客户端渲染(CSR)
页面仅在浏览器中渲染,服务端返回空 HTML。
工作流程
1. 用户请求 → 2. 服务器返回空 HTML + JS → 3. 浏览器下载 JS
↓
4. 页面空白 ← 等待 JS 执行 ← 5. JS 执行完毕,页面渲染CSR 的问题
- 用户在 JS 加载完之前看到的是空白页面
- 搜索引擎爬虫看到的也是空白页面(虽然 Google 爬虫能执行 JS,但效果不如 SSR)
- 低端设备(手机)上 JS 执行可能很慢
适用场景
- 不需要 SEO 的应用(后台管理系统)
- 重交互的应用(在线编辑器、游戏)
配置方式
全局禁用 SSR:
export default defineNuxtConfig({
ssr: false,
})特定路由禁用 SSR:
export default defineNuxtConfig({
routeRules: {
'/admin/**': { ssr: false }, // 管理后台用 CSR
'/dashboard/**': { ssr: false }, // 仪表盘用 CSR
},
})最佳实践
不要全局禁用 SSR,只对不需要 SEO 的路由禁用。这样首页、博客等需要 SEO 的页面仍然是 SSR。
混合渲染
不同路由使用不同渲染策略,通过 routeRules 配置:
export default defineNuxtConfig({
routeRules: {
// 首页:SSR + 缓存 1 小时(SWR)
'/': { swr: 3600 },
// 博客列表:SSR + 缓存 1 小时
'/blog/**': { swr: 3600 },
// 博客文章:ISR,60秒后重新验证
'/blog/**': { isr: 60 },
// 管理后台:纯 CSR
'/admin/**': { ssr: false },
// API:允许跨域
'/api/**': { cors: true },
// 旧页面:重定向
'/old-page': { redirect: '/new-page' },
// 静态预渲染
'/about': { prerender: true },
},
})混合渲染是 Nuxt 的核心优势
——你不需要为整个网站选择一种渲染模式,不同页面可以用不同的策略。
routeRules 选项详解
| 选项 | 类型 | 说明 | 典型用途 |
|---|---|---|---|
ssr | boolean | 是否启用 SSR | 后台页面设 false |
swr | number | boolean | Stale-While-Revalidate 缓存秒数 | 内容不常变的页面 |
isr | number | boolean | Incremental Static Regeneration | 博客文章等定时更新的内容 |
prerender | boolean | 构建时预渲染 | 关于页等不变的内容 |
redirect | string | 重定向目标 | 旧 URL 迁移到新 URL |
cors | boolean | 启用 CORS | API 跨域访问 |
headers | object | 自定义响应头 | 安全头、缓存策略 |
SWR vs ISR 的区别
| 特性 | SWR | ISR |
|---|---|---|
| 全称 | Stale-While-Revalidate | Incremental Static Regeneration |
| 工作方式 | 先返回缓存,后台更新 | 等缓存过期后重新生成 |
| 用户体验 | 总是能快速看到内容 | 过期后可能短暂等待 |
| 适合 | 需要快速响应的页面 | 可以容忍短暂过期的页面 |
简单记忆
SWR = "先给旧的,再更新";ISR = "过期了就重新生成"。
静态站点生成(SSG)
构建时生成所有页面的静态 HTML:
npx nuxt generateSSG 和 SSR 的区别
| 特性 | SSR | SSG |
|---|---|---|
| 何时生成 HTML | 每次用户请求时 | 构建时一次性生成 |
| 内容更新 | 实时 | 需要重新构建 |
| 服务器 | 需要 Node.js 服务器 | 不需要,纯静态文件 |
| 部署 | 需要服务器 | 任何静态托管(GitHub Pages 等) |
| 适合 | 内容经常变化的网站 | 内容不常变化的网站 |
SSG 的最大优势
不需要服务器!你可以把生成的静态文件放到 GitHub Pages、Cloudflare Pages 等免费托管平台上。
export default defineNuxtConfig({
// 可以配合 routeRules 做部分预渲染
routeRules: {
'/api/**': { cors: true },
},
})边缘渲染(ESR)
在边缘节点(CDN)上运行服务端渲染:
export default defineNuxtConfig({
nitro: {
preset: 'cloudflare-pages', // 或 'vercel-edge'
},
})什么是"边缘"?
传统架构中,你的服务器在某个固定位置(如美国)。亚洲用户访问时,请求要跨越太平洋,延迟很高。"边缘"指的是全球分布的 CDN 节点——用户访问时,由离他最近的节点处理,速度更快。
| 部署方式 | 服务器位置 | 延迟 |
|---|---|---|
| 传统服务器 | 固定位置(如美国) | 亚洲用户可能 200ms+ |
| 边缘渲染 | 全球节点 | 通常 < 50ms |
支持的边缘预设:
cloudflare-pagesvercel-edgenetlify-edgedeno-deploy
渲染模式对比
| 特性 | SSR | CSR | SSG | 混合 |
|---|---|---|---|---|
| 首屏速度 | 快 | 慢 | 最快 | 按需 |
| SEO | ✅ 优秀 | ❌ 差 | ✅ 优秀 | 按需 |
| 动态内容 | ✅ | ✅ | ❌ | ✅ |
| 服务器负载 | 中 | 低 | 无 | 中 |
| 部署难度 | 需要服务器 | 需要服务器 | 纯静态 | 按需 |
| 适用场景 | 通用 | 后台 | 博客/官网 | 全场景 |
渲染模式选择指南
需要 SEO?
├── 是 → 内容变化频繁?
│ ├── 是 → SSR 或混合渲染(SWR/ISR 缓存)
│ └── 否 → SSG(nuxt generate,最简单最便宜)
└── 否 → 重交互?
├── 是 → CSR(ssr: false)
└── 否 → SSR(默认就好)独立开发者建议
- 博客/官网 → SSG(免费部署,不需要服务器)
- 全栈应用 → SSR(需要数据库、用户系统等)
- 管理后台 → 混合渲染(公开页面 SSR,后台 CSR)
- 不确定 → 先用默认 SSR,后面再调整
常见问题
Hydration 不匹配警告
[Vue warn]: Hydration mismatch这意味着服务端渲染的 HTML 和客户端渲染的结果不一致。常见原因:
- 在模板中使用了
Date.now()或Math.random() - 在服务端和客户端有不同的条件判断
- 使用了浏览器 API(如
window.innerWidth)
解决方案:把这些代码放在 onMounted 中或用 <ClientOnly> 包裹。
SSG 构建很慢
如果页面很多(如几千篇文章),nuxt generate 会很慢。解决方案:
- 使用 ISR 代替全量 SSG
- 使用
routeRules只预渲染关键页面 - 使用增量生成(只生成变化的页面)