混合渲染架构设计
真实产品不会只用一种渲染模式——首页需要 SSG 的极致速度、视频详情需要 ISR 的近实时更新、工作台需要 SSR 的个性化渲染、设置页只需要 SPA。Nuxt4 的
routeRules让你在同一个项目中按路由混合使用所有渲染策略,这是 Nuxt 区别于其他框架的核心竞争力。本章系统讲解混合渲染的架构设计、CDN 缓存策略,并给出 AI 视频平台的完整架构方案。
1. routeRules 按路由配置渲染策略
1.1 渲染模式全景
Nuxt4 支持 5 种渲染模式,每种都可以按路由独立配置:
| 模式 | 配置 | 渲染时机 | 适用场景 |
|---|---|---|---|
| SSR | ssr: true(默认) | 每次请求 | 个性化内容、实时数据 |
| SSG | prerender: true | 构建时 | 静态内容、落地页 |
| ISR | isr: seconds | 首次请求 + 定期刷新 | 高流量公共页面 |
| SWR | swr: seconds | 立即返回缓存,后台刷新 | 列表页、分类页 |
| SPA | ssr: false | 仅客户端 | 管理面板、不需要 SEO |
1.2 routeRules 完整语法
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 精确路径
'/': { prerender: true },
'/about': { prerender: true },
// 通配符
'/blog/**': { isr: 3600 },
'/api/**': { cors: true },
// 动态参数
'/videos/**': { isr: 60 },
// 多个规则组合
'/admin/**': {
ssr: true,
headers: { 'X-Frame-Options': 'DENY' },
},
// 客户端渲染
'/settings/**': { ssr: false },
},
})1.3 routeRules 合并规则
当多个规则匹配同一个路由时,更具体的规则覆盖更宽泛的规则:
routeRules: {
'/videos/**': { isr: 60 }, // 所有视频页缓存 60s
'/videos/featured': { isr: 300 }, // 精选视频缓存 5 分钟(覆盖上面的 60s)
'/videos/live/**': { ssr: true }, // 直播视频实时 SSR(覆盖上面的 ISR)
}1.4 所有可用的 routeRules 属性
interface NitroRouteConfig {
// 渲染模式
ssr?: boolean // true = SSR, false = SPA
prerender?: boolean // true = 构建时预渲染
isr?: number | boolean // ISR 缓存秒数,true = 永不过期
swr?: number | boolean // SWR 缓存秒数
// HTTP 头
headers?: Record<string, string>
// 缓存
cache?: {
maxAge?: number // 缓存时间(秒)
staleMaxAge?: number // stale 缓存时间
swr?: boolean // 是否启用 SWR
}
// CORS
cors?: boolean
// 重定向
redirect?: string | { to: string; statusCode?: number }
// 代理
proxy?: string
}2. CDN 缓存头配置
2.1 HTTP 缓存头基础
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 静态资源:长期缓存
'/_nuxt/**': {
headers: {
'Cache-Control': 'public, max-age=31536000, immutable',
},
},
// SSG 页面:CDN 缓存 1 小时,浏览器缓存 5 分钟
'/blog/**': {
prerender: true,
headers: {
'Cache-Control': 'public, s-maxage=3600, max-age=300',
},
},
// ISR 页面:CDN 缓存 60 秒,过期后返回 stale + 后台刷新
'/videos/**': {
isr: 60,
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=300',
},
},
// SSR 页面:不缓存
'/studio/**': {
headers: {
'Cache-Control': 'private, no-cache, no-store',
},
},
},
})2.2 缓存头参数详解
| 指令 | 含义 |
|---|---|
public | CDN 和浏览器都可以缓存 |
private | 只有浏览器可以缓存(包含用户数据时使用) |
max-age=N | 浏览器缓存 N 秒 |
s-maxage=N | CDN 缓存 N 秒(覆盖 max-age) |
stale-while-revalidate=N | 缓存过期后,允许返回 stale 内容 N 秒,同时后台刷新 |
no-cache | 每次都要和服务器验证(但可以缓存) |
no-store | 完全不缓存 |
immutable | 内容永远不变(配合哈希文件名使用) |
2.3 CDN 缓存策略矩阵
SEO 重要?
/ \
是 否
/ \
内容变化频率? SPA(ssr: false)
/ | \
很少 偶尔 频繁
| | |
SSG ISR SSR
(prerender) (isr) (ssr)
| | |
Cache: Cache: Cache:
永久 s-maxage no-store
immutable + SWR private
2.4 Vary 头:按条件缓存不同版本
// 根据设备类型返回不同缓存版本
routeRules: {
'/videos/**': {
headers: {
'Vary': 'Accept-Encoding, User-Agent',
'Cache-Control': 'public, s-maxage=60',
},
},
}3. AI 视频平台混合架构设计
3.1 架构全景图
CDN (Cloudflare / Vercel Edge)
│
┌───────────────────────┼───────────────────────┐
│ │ │
静态资源 (SSG) 缓存层 (ISR/SWR) 源站 (SSR)
│ │ │
/_nuxt/* (immutable) /videos/** (ISR 60s) /studio/** (SSR)
/ (prerender) /categories/** (SWR 300s) /admin/** (SSR)
/about (prerender) /search (SWR 30s) /api/** (dynamic)
/pricing (prerender)
/blog/** (prerender)
3.2 完整配置
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// ── 第一层:SSG(构建时生成,CDN 永久缓存)──
'/': { prerender: true },
'/about': { prerender: true },
'/pricing': { prerender: true },
'/features': { prerender: true },
'/terms': { prerender: true },
'/privacy': { prerender: true },
'/blog/**': { prerender: true },
'/help/**': { prerender: true },
// ── 第二层:ISR/SWR(CDN 缓存 + 定期刷新)──
// 视频详情页:高流量,ISR 60 秒
'/videos/**': {
isr: 60,
headers: {
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=600',
},
},
// 分类/标签页:中流量,SWR 5 分钟
'/categories/**': {
swr: 300,
headers: {
'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=1800',
},
},
// 搜索结果:SWR 30 秒(短缓存,保持较新)
'/search': {
swr: 30,
headers: {
'Cache-Control': 'public, s-maxage=30, stale-while-revalidate=60',
},
},
// ── 第三层:SSR(每次请求实时渲染)──
'/studio/**': {
ssr: true,
headers: {
'Cache-Control': 'private, no-cache',
'X-Robots-Tag': 'noindex',
},
},
'/admin/**': {
ssr: true,
headers: {
'Cache-Control': 'private, no-store',
'X-Frame-Options': 'DENY',
'X-Robots-Tag': 'noindex',
},
},
// ── 第四层:SPA(仅客户端渲染)──
'/settings/**': {
ssr: false,
headers: { 'X-Robots-Tag': 'noindex' },
},
// ── API 路由 ──
'/api/**': {
cors: true,
headers: { 'Cache-Control': 'no-store' },
},
'/api/videos/trending': {
cache: { maxAge: 60 }, // API 级别缓存
},
// ── 静态资源(构建产物,含哈希,永久缓存)──
'/_nuxt/**': {
headers: {
'Cache-Control': 'public, max-age=31536000, immutable',
},
},
},
})3.3 不同渲染模式的页面设计
<!-- SSG 页面:/pricing — 构建时确定内容 -->
<script setup lang="ts">
defineRouteRules({ prerender: true })
// 构建时获取价格方案(如果价格变化,需要重新构建)
const { data: plans } = await useFetch('/api/pricing/plans')
</script>
<!-- ISR 页面:/videos/[id] — 缓存 + 定期刷新 -->
<script setup lang="ts">
// ISR 已在 nuxt.config 中配置,页面代码和 SSR 完全一样
const route = useRoute()
const { data: video } = await useFetch(`/api/videos/${route.params.id}`)
</script>
<!-- SSR 页面:/studio — 每次请求实时获取用户数据 -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
const { user } = useAuth()
const { data: projects } = await useFetch('/api/studio/projects', {
headers: useRequestHeaders(['cookie']), // 透传用户 Cookie
})
</script>
<!-- SPA 页面:/settings — 纯客户端 -->
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
// 所有数据在客户端获取(没有 SSR,没有 Payload)
const { data: settings, refresh } = useFetch('/api/user/settings', {
server: false, // 明确只在客户端获取
})
</script>3.4 性能监控:验证渲染模式生效
// app/plugins/render-mode-debug.server.ts
export default defineNuxtPlugin((nuxtApp) => {
if (process.env.NODE_ENV !== 'development') return
const event = useRequestEvent()
if (!event) return
nuxtApp.hook('app:rendered', () => {
const route = useRoute()
console.log(`[Render] ${route.path} — SSR executed`)
})
})在浏览器中检查响应头:
# 检查缓存策略是否生效
curl -I https://aivideo.example.com/videos/abc123
# 预期看到:
# Cache-Control: public, s-maxage=60, stale-while-revalidate=600
# X-Nitro-Prerender: true(如果是 ISR 缓存命中)3.5 架构决策树
为一个新页面选择渲染模式时,按以下决策树判断:
这个页面需要 SEO 吗?
├── 否 → SPA(ssr: false)
└── 是 → 内容对每个用户都一样吗?
├── 否 → SSR(个性化内容)
└── 是 → 内容多久变化一次?
├── 几乎不变 → SSG(prerender: true)
├── 偶尔变化(分钟级) → ISR(isr: seconds)
└── 经常变化(秒级) → SWR(swr: seconds)
本章小结
- 混合渲染:Nuxt4 允许在同一项目中按路由使用 SSG/ISR/SWR/SSR/SPA 五种模式
- routeRules:在
nuxt.config.ts中按路径模式配置渲染策略和 HTTP 头 - CDN 缓存:
s-maxage控制 CDN 缓存、stale-while-revalidate实现 SWR - 架构设计:落地页 SSG → 公共内容 ISR → 个性化 SSR → 管理面板 SPA
- 决策标准:根据 SEO 需求、内容变化频率、是否个性化来选择渲染模式
下一章深入 Nuxt4 的数据获取核心——useFetch 与 useAsyncData 的深度对比。