技术文章/工程化

Nuxt 3 的渲染模式怎么选:SSR、SSG 还是 ISR

「这个项目该用 SSR 还是 SSG」是我被问得最多的问题之一。答案从来不是"哪个更好",而是"你的内容什么时候变"。

三种模式到底差在哪

模式 渲染时机 内容新鲜度 服务器开销
SSG 构建时 每次部署更新
SSR 每次请求 实时
SWR / ISR 首次请求 + 过期重建 秒级延迟

做一个真实的对照实验

拿这个博客的首页做基准,同一篇文章数据、同一台机器:

bash
# 全量静态生成
npx nuxi generate

# 服务端渲染 + 缓存
npx nuxi build && node .output/server/index.mjs

实测结果(本地取 20 次中位数):

模式 TTFB 内容更新延迟
SSG 12ms 需重新部署
SSR 61ms 实时
SWR(maxAge 300) 14ms ≤ 300s

SSG 的 12ms 是磁盘直读,快得没有悬念;但它要求"内容不变",而博客恰恰是一直在变的。

我的选择:SWR

对个人博客来说,"改完立刻可见"和"访问足够快"这两个需求是同时存在的。纯 SSG 满足不了前者,纯 SSR 又浪费——一篇文章的 HTML 在几分钟内不会有任何变化。

Nuxt 里只需要一行:

ts
export default defineNuxtConfig({
  routeRules: {
    '/': { swr: 300 },
    '/post/**': { swr: 600 },
    '/admin/**': { ssr: false, headers: { 'cache-control': 'no-store' } },
  },
})

注意 /admin/** 那条:后台页面绝对不能缓存,也不能被搜索引擎抓到,no-store 是底线。

一个容易踩的坑

SWR 的缓存键默认只包含路径。如果你改了文章标题,而缓存还没过期,访问者看到的仍然是旧页面。解决办法是把内容的版本号拼进缓存键

ts
const key = `post:${slug}:${post.updatedAt.getTime()}`

这样改稿会自然产生新的缓存条目,旧条目到期自动回收,不需要手动清缓存。

结论

  • 内容基本不变 → SSG
  • 内容实时性要求高、并发低 → SSR
  • 内容偶尔变、流量不小 → SWR(大多数博客都属于这一类)
← 上一篇让类型自己说话:我如何组织一个中等规模项目的类型层

评论

还没有评论,坐个沙发?