3.3 SSG与混合渲染策略


3.3 SSG 与混合渲染策略

第一棒不只有"请求来了现跑"一种跑法。本节讲三种变奏:构建期把页面提前跑完(SSG)、缓存后按间隔再生(ISR 与 SWR)、以及用 routeRules 给全站逐页配棒(混合渲染)。它把 1.2 的选型表落成可执行的配置,并为第 9 章的部署决策提供依据。

SSG:把整场比赛提前录好

nuxt generate 触发静态生成:Nuxt 从首页出发做爬取,把能发现的路由逐个渲染成 HTML 文件,连同静态资源一起产出。部署时不需要 Node 服务器,任何静态托管都能跑。

页面清单有两个来源:

// nuxt.config.ts export default defineNuxtConfig({ // 来源一:routeRules 显式声明要预渲染的路径 routeRules: { '/': { prerender: true }, '/about': { prerender: true }, }, // 来源二:nitro.prerender.additionalRoutes 补充爬虫发现不了的路径 nitro: { prerender: { additionalRoutes: ['/products/1', '/products/2'], // 动态路由要手工报备 crawlLinks: true, // 从已发现页面沿链接继续爬(默认开) }, }, })

动态路由是 SSG 的经典坑:products/[id].vue 有无数可能的 id,爬虫无从枚举,必须通过 additionalRoutes、sitemap 或一个返回路径清单的数据源显式报备。构建日志里会列出每个预渲染页面的状态,看到 503 或超时通常是页面在构建期请求了不可达的接口。

ISR 与 SWR:静态的速度,动态的新鲜

纯 SSG 的死穴是内容更新要重新构建。两条折中路:

  • SWR(stale-while-revalidate):请求命中缓存立即返回旧版,同时后台按条件触发再生。用户永远先拿到快的内容,新鲜度稍滞后;
  • ISR(incremental static regeneration):带固定间隔的定时再生,语义与主流平台的 ISR 对齐。
routeRules: { // 商品页:SWR,缓存十分钟内直接回,过期后台再生 '/products/**': { swr: 600 }, // 文档页:ISR,每小时再生一次 '/docs/**': { isr: 3600 }, }

两者的微妙差别在于触发方式:swr 依赖 Nitro 内置缓存(可配 Redis 等存储后端,多实例部署时共享缓存),isr 则面向支持该语义的托管平台。中小项目多数场景用 swr 即可,其缓存行为完全在你的应用内可控。

图 3-2:routeRules 混合渲染矩阵

图 3-2:routeRules 混合渲染矩阵

动手验证缓存行为

在实验项目里加一个时间页面,肉眼观察缓存:

<!-- pages/now.vue --> <script setup> // 服务端渲染时生成的时间戳,用来判断这版 HTML 是何时产的 const { data } = await useFetch('/api/now') </script> <template> <div> <p>服务器认为现在是:{{ data.now }}</p> <p>刷新几次,看这个时间多久变一次</p> </div> </template>
// server/api/now.get.ts:返回服务器当前时间 export default defineEventHandler(() => ({ now: new Date().toISOString() }))

配置 /now: { swr: 10 } 后反复刷新:十秒内时间不变(命中缓存),过十秒先返回旧值、下一次刷新变成新值(后台再生完成)。把规则改成 ssr: true(默认),每次刷新时间都变。这个五分钟实验胜过十页文档。

预渲染与运行时渲染的取舍清单

  • 内容更新频率:发布会级(低频)→ prerender;分钟级 → swr;每请求变 → SSR;
  • 流量规模:高流量页面尽量推向静态侧,服务器渲染留给真正需要的页面;
  • 个性化程度:因用户而异的内容不做 SSG(缓存里存不了"每个人"的版本),用 ssr:false 或客户端取数;
  • 部署目标:全静态产物可上任意 CDN;swr/isr 需要能跑 Nitro 的环境(第 9 章的部署矩阵接续此话题)。

构建产物的验收与回滚

预渲染跑完别急着发布,先验收产物。打开 .output/public,核对三件事:预期的 HTML 文件都在(对照 additionalRoutes 与爬虫清单,缺页通常是构建期接口失败,日志里搜错误);HTML 内容正确(抽查两三个页面,动态路由的参数渲染进了正文而不是空壳);内部链接可达(页面里的站内链接对应的目标文件存在,死链会同时伤用户与爬虫)。

回滚预案同样重要:静态产物的好处是版本即目录,保留前几版的产物(构建号命名),出问题时 CDN 或静态服务器切回旧目录即可,秒级完成。这比 SSR 应用的回滚(重新部署进程)轻得多——静态形态的运维红利,一半在发布、一半在回滚。

ISR/SWR 的回滚有个额外注意点:缓存里可能存着"坏版本"的页面,切回旧代码后要把缓存一并清掉,否则用户继续看到坏内容而你以为已经修好了。Nitro 的 storage 按命名空间组织,清理时按业务前缀批量删,别全量清缓存(会把无害的热缓存也干掉,流量洪峰直接砸到源站)。

⚠️ 常见坑:给带查询参数的页面配 swr。默认缓存键不含 query,/search?kw=a/search?kw=b 可能命中同一份缓存,用户搜 A 看到 B 的结果。此类页面要么保持 SSR,要么在缓存键里显式纳入 query。

💡 关键直觉:routeRules 是"渲染模式的路由表"——先列全站路由清单,逐条问 1.2 的三问(谁渲染/何时/数据何时取),答案写进这张表,渲染架构就定稿了。

本节要点回顾

  • SSG 两个清单来源:爬虫沿链接发现 + additionalRoutes 显式报备,动态路由必须报备;
  • SWR 先回旧再刷新,依赖 Nitro 缓存(可外接 Redis);ISR 定时再生,语义对齐托管平台;
  • 默认 SSR:不配规则的路由走请求时渲染,实时但耗服务器;
  • ssr:false 出壳渲染:后台与个人页的省服务器方案,SEO 不敏感时用;
  • 缓存键陷阱:带 query 的页面慎用缓存规则,必要时把 query 纳入键;
  • 五分钟实验:时间页加 swr 刷新,肉眼确认缓存与再生行为。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U