渲染光谱梳理

SSG → ISR → SSR → Streaming → PPR 不是五个开关而是一条光谱:按首字节来源、数据新鲜度与服务器成本定位每格,按路由甚至按组件混用

一条光谱,五种落点

从左到右:静态程度递减、实时性与服务器成本递增

SSG

构建期一次渲染,永久静态

首字节来源
CDN 上的静态 HTML 文件
数据新鲜度
冻结在构建时刻
服务器成本
几乎为零(只有托管)
ISR

静态缓存 + 过期后台重建

首字节来源
CDN 缓存(stale 也先返回旧版)
数据新鲜度
最长落后一个 revalidate 窗口
服务器成本
极低(仅偶发重建)
打开这一格
SSR

每个请求在服务器现渲染

首字节来源
服务器渲染完才发出
数据新鲜度
实时(请求时刻的数据)
服务器成本
每请求一次渲染,随流量线性增长
打开这一格
Streaming

SSR 的分段形态,壳先到

首字节来源
静态壳立即吐出,慢数据分段补
数据新鲜度
实时(同 SSR)
服务器成本
同 SSR,连接占用更久
打开这一格
PPR

静态壳预渲染 + 动态洞流式补

首字节来源
CDN 静态壳 + 洞的流式分段
数据新鲜度
壳冻结 / 洞实时,按组件各取所需
服务器成本
壳零成本,洞按请求计
打开这一格

每格什么时候用它

决策要点,而非 API 背诵

SSG
  • 内容对所有访客一致,且更新以「天/周」计:文档、营销页、博客正文
  • 流量越大越划算:渲染成本与请求量彻底脱钩
  • 需要最强 SEO 与最稳 TTFB 的落地页
  • 本页自身即是 SSG 实例:无取数、无动态 API,构建期预渲染后永久静态
ISR
  • 内容会更新但能容忍分钟级延迟:文章列表、商品目录、榜单
  • 想要 SSG 的成本,又不想每次改内容都重新部署
  • 本站实现:取数函数标 "use cache" + cacheLife({ revalidate: 60 });配合 cacheTag/revalidateTag 可按事件精确失效,逼近实时
SSR
  • 数据必须实时:库存、价格、仪表盘
  • 内容依赖 cookie/会话,千人千面(缓存无法共享)
  • 页面量少而实时性要求高,不值得为它设计缓存失效
Streaming
  • 页面必须动态,但内部数据有快有慢:慢的包进 Suspense,不拖整页
  • 首屏可以先给框架与快数据,让用户尽早看到「活的页面」
  • AI 生成、搜索聚合等天然分段产出的场景
PPR
  • 一页之内动静悬殊:商品页(描述静态 + 推荐/库存动态)是教科书场景
  • 想把「按路由选策略」细化到「按组件选策略」
  • 本站已全站开启 cacheComponents:PPR 专题即是活演示(壳静洞动可刷新验证)

渲染是光谱,不是开关

同一应用按路由混用;本站开启 Cache Components 后更可按组件混用

  • 旧模型(Next 15 及以前)策略的粒度是路由段:每个 page/layout 用dynamic/revalidate各自声明,一个站点同时存在 SSG 文档页、ISR 列表页、SSR 仪表盘是常态
  • 本站现行(cacheComponents):路由段配置已移除,缓存声明下沉到组件/函数上的"use cache"—— 同一页内静态壳与动态洞共存,build 输出用 ○ / ◐ / ƒ 标注每条的落点
  • 不要问「这个项目用 SSR 还是 SSG」,要问「这个路由的数据,变化频率 × 个性化程度 × SEO 要求,落在光谱哪一格」
  • 选型的默认方向是「尽量靠左」:能用静态就不要动态,动态部分用 Suspense 隔离成洞,而不是把整页拖下水