混合渲染架构设计

真实产品不会只用一种渲染模式——首页需要 SSG 的极致速度、视频详情需要 ISR 的近实时更新、工作台需要 SSR 的个性化渲染、设置页只需要 SPA。Nuxt4 的 routeRules 让你在同一个项目中按路由混合使用所有渲染策略,这是 Nuxt 区别于其他框架的核心竞争力。本章系统讲解混合渲染的架构设计、CDN 缓存策略,并给出 AI 视频平台的完整架构方案。

1. routeRules 按路由配置渲染策略

1.1 渲染模式全景

Nuxt4 支持 5 种渲染模式,每种都可以按路由独立配置:

模式配置渲染时机适用场景
SSRssr: true(默认)每次请求个性化内容、实时数据
SSGprerender: true构建时静态内容、落地页
ISRisr: seconds首次请求 + 定期刷新高流量公共页面
SWRswr: seconds立即返回缓存,后台刷新列表页、分类页
SPAssr: 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 缓存头参数详解

指令含义
publicCDN 和浏览器都可以缓存
private只有浏览器可以缓存(包含用户数据时使用)
max-age=N浏览器缓存 N 秒
s-maxage=NCDN 缓存 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 的数据获取核心——useFetchuseAsyncData 的深度对比。