SSR/SSG 的定义 之前在博客上有提过。对比 CSR、SSR、SSG、ISR,它们的优缺点和适用场景分别是什么?
一、为什么要使用 SSR/SSG?(解决传统前端渲染的核心痛点)
传统 React/Vue 项目是「客户端渲染(CSR)」:浏览器先加载空 HTML → 下载 JS → 执行 JS 渲染页面,存在两大致命问题,而 SSR/SSG 能完美解决:
| 痛点(CSR 客户端渲染) | SSR/SSG 的解决方案 |
|---|---|
| 白屏时间长,用户体验差 | - SSR:服务器返回完整 HTML,浏览器直接渲染,首屏无白屏;- SSG:预生成静态 HTML,加载速度比 SSR 更快(静态文件可放 CDN)。 |
| SEO 不友好,爬虫抓不到内容 | 爬虫直接抓取服务器返回的完整 HTML(含页面内容),而非空壳 HTML,百度 / 谷歌能正常索引页面。 |
| 首屏性能指标差(LCP/FCP 高) | 首屏渲染时间(LCP)大幅降低,符合核心 Web 指标要求,提升页面排名。 |
| 弱网 / 低配置设备体验差 | 低配置手机 / 弱网环境下,无需等待 JS 下载执行,先看到内容,体验更优。 |
二、SSR vs SSG 适用场景(选对才有用)
| 特性 | SSR(服务端渲染) | SSG(静态生成) |
|---|---|---|
| 渲染时机 | 每次用户请求时(运行时) | 项目构建时(预渲染) |
| 性能 | 较快(动态渲染有开销) | 极快(静态文件,CDN 分发) |
| 动态内容支持 | 完美支持(如用户中心、实时数据、个性化内容) | 仅支持静态内容(如官网、博客、文档、商品列表(非实时)) |
| 部署复杂度 | 较高(需服务器运行 Node.js 等环境) | 极低(静态文件可部署到任何静态托管平台:GitHub Pages/Vercel/Netlify) |
| 维护成本 | 较高(需维护服务端环境) | 极低(静态文件无运行时依赖) |
典型适用场景:
- 用 SSG:企业官网、博客、文档站、产品介绍页、帮助中心(内容固定 / 更新频率低);
- 用 SSR:电商商品详情页(部分动态)、用户中心、后台管理系统(需登录)、实时数据看板;
- 用 ISR:电商商品页(构建时预生成,数据更新时增量刷新)、新闻资讯页(定时更新)。
三、什么时候不用 SSR/SSG?
- 纯后台管理系统(无需 SEO,仅内部使用);
- 内容高度动态且更新极频繁(如实时聊天、股票行情)→ 用 CSR + 首屏骨架屏更合适;
- 小项目 / 原型(SSR/SSG 增加开发 / 部署成本,性价比低)。
四、核心总结
- SSG:为「静态内容」而生,极致性能 + 极简部署,优先选;
- SSR:为「动态内容」而生,解决白屏 + SEO,部署稍复杂;
两者核心价值:提升首屏体验 + 优化 SEO,是生产环境 React/Vue 项目的标配方案(尤其 ToC 业务)。
五、基于Next.js实现SSR/SSG
步骤 1:初始化 Next.js 项目
1 | # 创建 Next.js 项目(默认支持 React 18) |
步骤 2:实现 SSG(静态生成)
SSG 是 Next.js 默认的渲染方式,通过 getStaticProps(页面级数据预取) + 构建时预渲染实现:
1 | // pages/index.js(Next.js 12/13 兼容,App Router 见下文) |
构建 & 验证 SSG:
1 | # 构建静态页面(生成 .next/static 目录) |
构建后,pages 下的所有页面会被预渲染为静态 HTML,访问时无白屏,SEO 友好。
步骤 3:实现 SSR(服务端渲染)
通过 getServerSideProps 替代 getStaticProps,每次请求时服务端动态渲染:
1 | // pages/user.js(用户中心,动态内容) |
验证 SSR:启动服务后访问 http://localhost:3000/user,查看页面源码(能看到完整的用户信息 HTML),且每次刷新都会触发 getServerSideProps 重新获取数据。
Next.js 13+ App Router 适配(最新推荐)
Next.js 13 推出了 App Router,用「React Server Components(RSC)」简化 SSR/SSG,核心逻辑:
1 | // app/page.js(默认 SSG,App Router 入口) |
关键配置(App Router):
cache: 'force-cache':默认 SSG,构建时缓存数据;cache: 'no-store':SSR,每次请求重新获取数据;next: { revalidate: 60 }:ISR,60 秒后重新生成页面。