资讯文章 资讯 · NEWS
静态生成、增量再生还是服务端渲染:目录站该怎么选这三种
2026-10-24 约 1,397 字 预计阅读 3 分钟 yiyunkj
静
讨论渲染策略之前,先把目标说清:我们要的是爬虫和用户拿到同一份带内容的 HTML,同时这份 HTML 尽量新。这两件事在某些方案里天然冲突,冲突的部分就是你要做选择的地方。

图片来源:网络,版权归原作者所有,侵权请联系删除
三种策略的本质差别
| 策略 | 什么时候生成 HTML | 适合 | 代价 |
|---|---|---|---|
| 静态生成 SSG | 构建时一次做成文件 | 分类页、说明页、政策页 | 改一个字要重建 |
| 增量再生 ISR | 首次请求后缓存,到期后台再生成 | 条目页、详情页 | 需要处理失效时机 |
| 服务端渲染 SSR | 每次请求现算 | 榜单、搜索结果、个化 | 每一次请求都有成本 |
这里还要注意一个常被忽略的点:服务端渲染同样返回完整 HTML,爬虫处理上没有障碍,麻烦的是时间和容量成本,不是可见。
增量再生的实际行为
以 Next.js 的 ISR 为例,两种触发方式:
一是基于时间,路由导出 revalidate 秒数。它的行为是经典的 stale-while-revalidate:过期后的第一个请求仍然拿到旧的缓存页面(不阻塞),同时在后台触发一次再生成;生成成功后替换缓存,之后的请求才是新的。
二是按需失效,调用 revalidatePath 或 revalidateTag。这种方式更精确:内容改了才重生,没改的不动。对于有 CMS 或后台审核流的目录站,应当以按需为主、时间为辅(给个兜底窗口)。
这里有个容易出错的组合:有一点容易踩:如果上层数据源自带缓存,再生成拿到的仍是旧数据,revalidate 白跑一趟。检查上游接口的 Cache-Control,必要时显式关掉它的 CDN 缓存。
三个真出过事的配置
缓存了错误的响应
再生成时如果数据源抖动返回了 500,某些配置下会把这个错误响应缓存进去,之后一段时间整页都是错误页。必须确认失败时保留旧版本,而不是替换,并在监控里做这件事的告警。
把个化内容塞进静态缓存
登录态、地域推荐、A/B 分组,只要混进了被静态化的页面,就会被不同的人反复看到。用户 A 看到用户 B 的收藏状态,属于典型事故。这一类内容要么延迟到客户端请求,要么干脆不要静态化。
多实例之间失效不同步
官方明确指出,多实例部署时 revalidate 事件默认是本地的:在实例 A 上调用,只有 A 的缓存失效,B 还在发旧内容。需要通过共享存储(如 Redis)配合 updateTags / refreshTags 做跨实例协调。这是「改了之后一半人看不到更新」最常见的解释。
目录站的分工建议
| 页面 | 策略 | 理由 |
|---|---|---|
| 分类页 | SSG + 构建触发 | 结构稳定,重建可控 |
| 条目详情页 | ISR + 审核通过时按需失效 | 更新有明确时间点 |
| 榜单 / 本周新增 | SSR 或短 TTL 的 ISR | 随时在变,别为难自己 |
| 搜索结果页 | SSR 且不缓存 | 组合爆炸,缓存命中率极低 |
| 政策 / 说明页 | SSG | 几乎不变 |
三条容易忘的一致要求
第一,canonical 在渲染前后必须一致。如果 ISR 再生成期间改变了 canonical 指向,爬虫看到的前后不一致会直接影响规范化的判定。
第二,lastmod 要对应真实的再生时间,不是构建时间。许多站点 sitemap 里的 lastmod 常年是 CI 跑的那天,等于告诉爬虫「没更新过」。
第三,HTML 与下一次导航所用的数据负载要一致。官方特别提到两者应当共存于同一份缓存条目,实践上就是:别给 HTML 和给客户端的数据接口设不同的 TTL 和失效策略,否则站内跳转时会出现「页面 A、数据 B」的错位。
策略没有最优解,只有和自己变更频率匹配的解。先把页面按「多久变一次」分三堆,再套模板,比整体选一种省心得多。