SSG 与 SSR:原理、取舍与 SEO 实战
做 SEO 的时候,你经常会听到一句话:“别做纯 CSR,选 SSR 或 SSG。”
但落到项目里,问题通常变成:
- 页面到底该 静态生成(SSG) 还是 服务端渲染(SSR)?
- 为什么都是“先返回 HTML”,SEO 和性能表现却差很多?
- 动态数据、个性化、频繁更新、海量页面……怎么兼顾?
这篇文档会把 SSG 与 SSR 的核心机制讲清楚,并给出面向 SEO 的选型与落地清单。
- 内容稳定 + 页面量大 + 希望极致性能与最低成本:优先 SSG(必要时再加 ISR/增量更新)。
- 内容强动态 + 个性化 + 需要实时数据/权限判断:优先 SSR(并配合 CDN/服务端缓存)。
- 最常见的真实情况是混合:公开内容页用 SSG/ISR,登录后页面用 SSR/CSR。
一、先把名词说清:你到底在“渲染”什么?
无论 SSG 还是 SSR,本质都在解决同一件事:让爬虫/用户尽快拿到“包含主要内容的 HTML”,而不是只拿到一个空壳。
页面渲染通常分两段:
- 首屏 HTML(可被抓取):标题、正文、列表等“主要内容”要出现在初始 HTML 中
- Hydration(水合,可交互):浏览器下载 JS,把静态 HTML 变成“能点击/能跳转/能提交”的应用
“SSG/SSR = 不需要 JS 了” 是误解。
多数现代框架(React/Vue)仍然需要在浏览器侧 Hydration 才能完成交互,只是 关键内容不再依赖浏览器执行 JS 才出现。
二、SSG 是怎么工作的(构建时生成)
SSG(Static Site Generation)把“生成 HTML”的时机放到构建阶段:提前把每个页面的 HTML 产物生成好,然后部署到 CDN。
2.1 SSG 的 SEO 与性能特点
- SEO 友好:初始 HTML 里就有标题、正文、结构化数据,爬虫抓取成本低
- 性能强:静态文件 + CDN,通常有更好的 TTFB 与稳定性
- 成本低:不需要为每次请求做服务端渲染,服务器压力小
2.2 SSG 的核心代价
- 数据新鲜度:构建之后内容变了,页面不会自动更新
- 构建耗时:页面越多,构建越慢(尤其是“万级页面”)
很多框架提供“增量静态生成/再验证”的能力:让页面先用静态方式响应,再在后台更新并逐步生效,从而兼顾性能与更新频率。
三、SSR 是怎么工作的(请求时生成)
SSR(Server Side Rendering)把“生成 HTML”的时机放到每次请求到来时:服务器拿到请求,拉取数据,生成 HTML,返回给用户/爬虫。
3.1 SSR 的 SEO 与业务优势
- 内容实时:每次请求都能拿到最新数据(新闻、库存、价格、权限)
- 更适合个性化:可根据 Cookie/登录态/地理位置渲染不同内容
- 状态码更自然:404/301/302 等可在服务端直接控制(对 SEO 很关键)
3.2 SSR 的核心代价
- 服务器开销更大:每次请求都要计算渲染
- 可用性更敏感:渲染链路依赖 API/数据库,任何抖动都可能影响出 HTML
- 缓存策略更复杂:既想“实时”,又想“快”,就需要分层缓存(CDN/应用缓存/数据缓存)
四、SSG vs SSR:用 SEO 视角做一次对比
| 维度 | SSG | SSR |
|---|---|---|
| HTML 生成时机 | 构建时 | 请求时 |
| 首屏内容可抓取性 | 很强(天然) | 很强(天然) |
| 内容更新频率 | 低~中(可配增量更新) | 高(天然实时) |
| TTFB(首字节) | 通常更低(CDN 静态) | 取决于渲染耗时与缓存 |
| 服务器成本 | 低 | 中~高 |
| “海量页面”能力 | 构建会变慢(需拆分/增量) | 请求会变多(需缓存/扩容) |
| 典型场景 | 文档、博客、营销页、帮助中心 | 新闻、商品详情(强动态)、搜索结果页、个性化首页 |
不管你是 SSG 还是 SSR,只要出现以下情况,SEO 都会显著变差:
- 关键内容在浏览器
useEffect之后才出现(爬虫可能抓不到) <title>/description/canonical等元信息只在客户端修改- 统一返回
200,但页面里写着“未找到”(应该返回404)
五、如何选型:一张决策图
六、实战:以 Next.js 为例理解落地方式
下面用 Next.js(Pages Router)快速演示 SSG 与 SSR 的写法,重点是理解“数据在什么时候拿、HTML 在什么时候生成”。
它把 SSG/SSR 的差异表达得很直观(getStaticProps vs getServerSideProps),便于迁移到 Nuxt、Remix 等框架的对应能力。
6.1 SSG:构建时生成页面
// pages/posts/[id].tsx
export async function getStaticPaths() {
const ids = await fetch('https://api.example.com/posts/ids').then((r) => r.json());
return { paths: ids.map((id: string) => ({ params: { id } })), fallback: false };
}
export async function getStaticProps({ params }: { params: { id: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.id}`).then((r) => r.json());
return { props: { post } };
}
要点:
getStaticProps:构建时拉取数据并生成 HTMLgetStaticPaths:告诉框架要生成哪些动态路由页面
如果内容需要“准实时”,可以加入再验证(ISR):
return { props: { post }, revalidate: 60 };
含义:页面最多每 60 秒更新一次(具体行为取决于部署平台实现)。
6.2 SSR:请求时生成页面
// pages/profile.tsx
export async function getServerSideProps({ req }: { req: { headers: Record<string, string> } }) {
const cookie = req.headers.cookie ?? '';
const user = await fetch('https://api.example.com/me', { headers: { cookie } }).then((r) => r.json());
return { props: { user } };
}
要点:
getServerSideProps:每次请求都会执行- 非常适合登录态、权限、强个性化内容(但记得做缓存与降级)
如果这是公开可索引的页面(比如商品详情),SSR 里要确保:
- 返回的 HTML 包含完整标题/正文/结构化数据
- 缺货/下架要么做明确的状态码策略(404/410/301),要么做可理解的替代页
七、SSG/SSR 的 SEO 清单(上线前自检)
- 初始 HTML 是否包含主要内容(不要依赖客户端二次渲染)
- title/description/canonical 是否在服务端就确定(不要只在客户端改)
- 分页/筛选页是否有 canonical 与 noindex 策略(避免重复内容)
- 404/重定向是否返回正确状态码(不是“200 + 文案提示”)
- 是否输出 sitemap.xml / robots.txt(便于收录与抓取预算管理)
- 结构化数据是否可被抓取(JSON-LD 推荐,且放在初始 HTML)
更多通用 SEO 细节可以配合阅读:SEO 搜索引擎优化完全指南。
八、常见坑与排查思路
- “看起来是 SSR/SSG,但爬虫抓到的是空页面”
- 用
view-source:或抓包看“返回的 HTML”是否有正文 - 不要只看 Elements(Elements 可能是 Hydration 后的 DOM)
- 用
- Hydration mismatch(服务端 HTML 与客户端渲染不一致)
- 避免在首屏渲染中使用
Date.now()/Math.random()等不稳定值 - 把“只在浏览器才知道的信息”(窗口尺寸、localStorage)延后处理
- 避免在首屏渲染中使用
- SSG 构建时间爆炸
- 拆分构建:按目录/语言/站点拆分
- 引入增量生成/按需生成,避免一次性生成全量页面
- SSR 性能波动大
- CDN/应用层缓存 + 数据层缓存分层做
- 给慢接口设置超时与降级(宁可展示旧数据,也别长时间白屏)
九、面试高频问答
Q1:SSG 和 SSR 最大区别是什么?
A:区别是 HTML 生成时机:SSG 在构建时生成静态 HTML;SSR 在每次请求时由服务器渲染生成 HTML。
Q2:为什么 SSR/SSG 更利于 SEO?
A:因为爬虫请求页面时就能拿到包含主要内容的 HTML,不需要依赖执行 JS 才能看到正文与元信息。
Q3:SSR 一定比 SSG 慢吗?
A:不一定。SSR 如果命中 CDN/服务端缓存也可以很快;但在“无缓存 + 渲染依赖多接口”的情况下,SSR 更容易慢且波动大。
Q4:SSG 的内容更新怎么解决?
A:常见做法是增量更新(ISR/再验证)、触发式重建(Webhook)、或对局部数据使用客户端请求(但要避免影响 SEO 关键内容)。
Q5:Hydration 是什么?为什么会出现 hydration mismatch?
A:Hydration 是浏览器把“服务端/静态 HTML”变成可交互应用的过程。Mismatch 往往来自“服务端渲染结果”和“客户端首次渲染结果”不一致,例如时间戳、随机数、依赖浏览器环境的逻辑。
Q6:为什么说“不要用 200 返回 404 页面”?
A:搜索引擎会把它当作正常页面收录,造成索引污染与重复内容;正确做法是返回 404(或 410)状态码。
Q7:哪些页面更适合 SSG?
A:文档、博客、营销页、帮助中心、公司介绍、长期稳定的落地页等。
Q8:哪些页面更适合 SSR?
A:强动态/强个性化页面,例如:登录态首页、订单中心、搜索结果页、库存价格实时变化的页面等。
Q9:如何在 SSR 场景提升性能?
A:关键是缓存:CDN 缓存(按路由/参数)、应用缓存(渲染结果缓存)、数据缓存(接口/数据库结果缓存),并结合超时与降级策略。
Q10:SSG/SSR 与 Core Web Vitals 有什么关系?
A:SSG/SSR 能提升首屏可见速度(FCP/LCP)并减少“白屏时间”。但最终指标还受资源体积、图片、布局稳定性、交互脚本等影响,渲染方式只是其中一环。