CSR、SSR 与 SSG
作为渲染模式对比入口,串起 CSR、SSR、SSG 的生成时机、数据新鲜度与性能取舍,并明确它们和 Server/Client Components 属于不同维度。
[!info] related notes
- 所属 MOC: 前端基础 MOC, 前端工程化 MOC
- 原子概念: 客户端渲染(CSR), 服务端渲染(SSR), 静态站点生成(SSG), Hydration
- 易混淆关系: React SSR、Hydration 与服务端组件, SPA vs MPA
- 框架实践: Next.js, Islands Architecture
CSR、SSR 与 SSG
它们在回答什么问题
CSR、SSR、SSG 可以先放在同一条“页面生成时机”轴上理解:
Build time Request time Browser time
│ │ │
SSG SSR CSR
它们主要回答:
首屏/主要页面结果是在什么时候、由谁准备出来的?
这和 React Server Component / Client Component 的“组件实现代码需要哪一侧 runtime”不是同一个维度。
三种模式
CSR:Client-Side Rendering
浏览器先拿到 HTML shell 与 JavaScript,再由客户端 React/Vue 等运行、取数并生成主要 UI。
常见链路:
HTML shell
↓
下载 JS
↓
启动应用
↓
client fetch
↓
render UI
优势:
- 客户端交互模型直接
- SPA 架构成熟
- 用户进入应用后很多交互不需要整页请求
代价:
- 首屏可能形成 HTML → JS → API → Data → UI waterfall
- 客户端 JavaScript、parse/execute 与主线程成本更高
- SEO / 首屏直出需要额外设计
SSR:Server-Side Rendering
请求到来时,服务器根据当前请求和数据生成 HTML/页面结果,再返回浏览器。
Request
↓
Server fetch / DB
↓
Render
↓
HTML
↓
Browser
适合:
- 用户专属内容
- 依赖 cookie / headers / search params 等请求时上下文
- 数据需要请求时保持新鲜
- 首屏内容希望直接可见
SSR 解决“请求时生成”,不等于自动减少所有客户端 JavaScript;有交互的区域通常仍需要客户端 runtime 与 Hydration。
SSG:Static Site Generation
在构建时或再验证阶段提前生成结果,用户访问时直接命中静态产物或缓存。
Build / Revalidate
↓
Render once
↓
Static / cached result
↓
CDN → Users
适合:
- 官网
- 博客
- 文档
- 稳定商品/内容页
- 可以容忍一定缓存窗口的公共内容
核心收益是把“每个请求都要计算”转成“提前计算并复用”。
核心对比
| 模式 | 主要生成时机 | 数据新鲜度 | 服务端请求成本 | 客户端 JS 压力 | 常见场景 |
|---|---|---|---|---|---|
| CSR | 浏览器运行时 | 客户端请求决定 | 可低 | 通常较高 | SPA、强交互局部 |
| SSR | 每次请求时 | 高,可读取请求上下文 | 较高,可缓存优化 | 取决于客户端边界 | 个性化 Dashboard、用户页 |
| SSG | 构建/再验证时 | 受构建或 revalidation 影响 | 低 | 取决于客户端边界 | 官网、博客、文档 |
现代框架通常是混合模型
不要把选择题理解成:
这个网站只能是 CSR / SSR / SSG 三选一
现代框架通常按 Route、数据甚至组件边界混合:
/about
→ Static / SSG
/dashboard
→ Request-time dynamic / SSR
→ 内部含 Client Components
/editor
→ Server-rendered shell
→ 大量 client interaction
所以“Dashboard 是强交互页面”并不推导出“Dashboard 必须 CSR”。例如 Next.js 可以在请求时用 Server Components 查询当前用户最新数据,然后只把编辑器、ThemeSwitcher、按钮等交互区域放到客户端。
与 Server / Client Components 是两个维度
这是最重要的易混淆点。
维度 A:页面什么时候生成?
SSG / SSR / CSR
维度 B:组件代码需要哪里运行?
Server Component / Client Component
因此:
Server Component + SSG ✅
Server Component + SSR ✅
Client Component + 预渲染 + Hydration ✅
Client-only CSR ✅
详见 React SSR、Hydration 与服务端组件。
选型不要只看“页面类型”
更稳的判断顺序是:
1. 能否在用户请求之前生成?
如果公共内容稳定,可以优先 Static / SSG。
2. 是否依赖请求时信息?
例如:
- 当前用户
- Cookie
- 权限
- 请求参数
- 最新实时数据
如果是,更接近 request-time dynamic / SSR。
3. 哪些交互真的必须浏览器执行?
再独立划分 Client Components,而不是因此把整个页面改成 CSR。
4. 数据新鲜度与缓存窗口是多少?
很多页面并非“静态或实时”二选一,而是可以使用 revalidation / cache policy,在性能与新鲜度之间取舍。
性能不要只看首屏 HTML
SSR / SSG 经常让内容更早可见,但真实性能还取决于:
- TTFB
- CDN / Cache hit
- HTML / RSC payload 体积
- Client JavaScript
- Hydration 范围
- 主线程任务
- 后续 API waterfall
因此:
SSR 不是性能银弹,CSR 也不是天然慢;关键在于工作被放在哪一侧、是否重复,以及用户必须等待哪条关键路径。
与 SPA / MPA 的区别
- SPA / MPA:页面导航与应用运行时如何组织。
- CSR / SSR / SSG:页面主要结果何时、在哪里生成。
两组概念可以组合,不能互相替代。
最短记忆方式
SSG = 提前生成
SSR = 请求时生成
CSR = 浏览器生成
然后永远补上一句:
这条轴不要和 Server Component / Client Component 混在一起。
学习检查
不看正文回答:
- CSR、SSR、SSG 最主要回答的是哪一个维度:导航模式、组件运行位置,还是页面生成时机?
- Build time、Request time、Browser time 分别对应哪种典型模式?
- 为什么 SSR 不自动等于性能更好?
- 为什么 SPA / MPA 与 CSR / SSR / SSG 可以交叉组合?
- Client Component / Server Component 为什么又是另一条轴?
- 一个新闻详情页、后台 Dashboard、营销落地页分别应先考虑哪些数据新鲜度和交互约束?
- 给一个新页面,不先选技术名词,按“何时能生成、是否依赖请求、需要多少客户端交互”完成决策。