next 精选推荐

增量静态再生 (ISR) 实战

HTMLPAGE 团队
22 分钟阅读

从缓存语义与一致性边界出发,讲清 ISR 的原理、适用场景与落地细节,并给出可直接复用的页面设计、失效策略与线上排障方法。

#Next.js #ISR #缓存 #SSG #SEO

增量静态再生 (ISR) 实战

ISR(Incremental Static Regeneration)经常被误解为“更聪明的 SSG”。

更准确的说法是:ISR 是一套把“静态化收益”与“内容更新需求”折中起来的缓存与再生成协议

它解决的核心矛盾是:

  • 你想要静态页面的性能与稳定性(低 TTFB、CDN 命中、高并发能力)
  • 你又希望内容能及时更新(分钟级甚至秒级)

这篇文章按“上生产能跑稳”为标准,讲清:

  • ISR 的工作原理与心智模型
  • 适用场景与反例
  • 页面设计(列表/详情/搜索)
  • 失效策略:时间驱动 vs 事件驱动
  • 线上排障:为什么更新不生效/为什么频繁回源

1. 先统一语言:你到底想解决什么?

在真实业务里,“内容更新”通常有三种等级:

  1. 允许延迟:比如文章页、帮助文档、营销页,更新延迟 5~30 分钟都能接受
  2. 弱一致:比如商品价格、库存展示(可能需要更短 TTL,但可以接受短时间旧值)
  3. 强一致:比如支付结果、权限信息,不能用 ISR 兜底

ISR 最适合第 1 类,谨慎用于第 2 类,不适合第 3 类。


2. ISR 的心智模型:把它当成“CDN 后的再生成缓存”

你可以把 ISR 看作两层:

  • CDN:缓存最终 HTML(或 RSC payload)
  • 应用(Next.js):缓存页面生成结果,并按规则触发再生成

关键点:

  • ISR 不是“每次请求都重新生成”,而是“绝大多数时候直接命中缓存”
  • 再生成是“受控发生”的

3. 两种驱动方式:时间驱动 vs 事件驱动

3.1 时间驱动(revalidate 秒数)

特点:

  • 简单
  • 稳定
  • 但更新延迟不可控(取决于 TTL 与访问触发)

适用:

  • 内容更新不频繁
  • 不需要“发布即生效”

3.2 事件驱动(按需再验证 / webhook)

特点:

  • 发布后可快速生效
  • 更可控
  • 需要你有“内容发布事件”与安全机制

适用:

  • CMS 发布文章
  • 商品信息变更
  • 专题页更新

4. 典型页面怎么做:列表 + 详情

4.1 详情页:优先事件驱动

详情页更新的最佳体验通常是“发布即生效”。

策略:

  • 详情页使用 ISR(或静态 + 按需再验证)
  • CMS 发布时调用 webhook,让应用对特定 path/tag 失效

4.2 列表页:注意“聚合页放大效应”

列表页(例如文章列表、商品列表)会被大量访问,且它的内容聚合了很多详情。

常见坑:

  • 每次新增一篇文章都要失效列表页
  • 导致列表页频繁再生成 → 回源增多

建议:

  • 列表页采用较长 TTL(例如 10~30 分钟)
  • 或把“最新内容”拆成单独模块,使用客户端请求/边缘 KV

5. 数据获取与缓存:别把 ISR 做成“慢 SSR”

ISR 的性能收益来自“生成一次 → 复用很多次”。

所以你要避免:

  • 页面生成时做大量慢查询
  • 页面生成时串行请求多个上游

实践建议:

  • 生成路径尽量轻(prefetch、批量接口、缓存)
  • 对上游请求设置超时
  • 做并行请求

6. 失效策略设计:从“靠感觉”到“有规则”

建议采用“域驱动失效”思路:

  • 文章:article:{slug}
  • 文章列表:article:list
  • 专题:topic:{name}

当某篇文章更新:

  • 必失效:article:{slug}
  • 可选失效:article:list(看你是否要求“列表立即出现最新文章”)

这样你能解释每一次失效,而不是“全站清缓存”。


7. 线上排障:ISR 最常见的 6 个问题

7.1 “发布了但页面不更新”

排查顺序:

  • webhook 是否触发?是否被鉴权拦截?
  • 失效的是正确的 path/tag 吗?
  • CDN 是否仍在强缓存旧内容?(看响应头、Cache-Status)

7.2 “页面更新了但 SEO 抓不到”

  • sitemap 是否更新
  • canonical/robots 是否正确
  • 是否把重要内容放在客户端渲染

7.3 “回源突然暴增”

常见原因:

  • TTL 设太短
  • 聚合页频繁失效
  • 缓存命中率被 query 污染(utm)

7.4 “某些地区更新很慢”

  • CDN 分区缓存
  • 边缘节点回源延迟

7.5 “低峰正常,高峰崩”

  • 再生成并发过高
  • 上游服务扛不住

策略:

  • 限制再生成并发
  • 对再生成做队列化

7.6 “用户态数据被缓存”

这是最危险的。

规则:

  • 用户态页面不要 ISR
  • 或把私有信息拆出(客户端请求)

8. 上线检查清单

  • 哪些路由使用 ISR?是否排除用户态页面
  • 详情页与列表页的 TTL 是否合理
  • 是否有事件驱动失效(CMS webhook)
  • CDN cache key 是否会被 query 污染
  • 是否有命中率/回源/QPS 监控
  • 再生成失败是否可观测(日志、报警)

总结

ISR 的正确用法是:

  • 把它当成“带可控失效的静态缓存系统”
  • 用规则设计失效,而不是全站清缓存
  • 用监控保证它在高峰依然稳定