想象你开了一家小餐馆。顾客走进来,你让他先坐下,然后才去后厨洗菜、切菜、炒菜,最后端上桌——顾客盯着空盘子等了十几分钟,这叫客户端渲染(CSR)。如果改为后厨提前备好食材,顾客点单后快速现炒,端上桌的是一盘热腾腾的完整菜品——这叫服务端渲染(SSR)。再往前一步,你在开店前就把所有菜做好封装,顾客进门直接拿走——这叫静态生成(SSG)。而混合渲染(ISR)像是预制菜每隔一段时间重新现做一次,既保留极速出餐的优势,又保证菜品新鲜度。 本文用“餐馆出餐”这条线贯穿始终,把CSR、SSR、SSG、ISR四种渲染方案的原理、优劣、适用场景用生活经验讲个通透。读完你不仅能看懂Next.js和Nuxt.js里的实现,还能在实际项目中做出正确的渲染选型。
对前端工程师和全栈开发者而言,掌握SSR与SSG的原理和选型,是构建高SEO、快首屏的生产级应用的核心能力,也是React/Vue框架进阶绕不开的一道坎。
目录
可视化演示
展示四种前端渲染模式:CSR客户端渲染、SSR服务端渲染、SSG静态生成、ISR增量静态再生,动态对比TTFB和SEO表现差异。
本节配有交互动效(进入视口后自动加载,约 3KB)。
CSR:客户端渲染(首屏慢) 红色为API请求(数据获取) 灰色为空HTML(白屏) 紫色为客户端渲染(JS执行) Flow: empty HTML -> JS load -> API fetch -> render CSR首屏需下载JS+请求数据+渲染,TTFB高SEO差但交互流畅
CSR的困境——现点现炒,顾客等不起
以前开川菜馆,顾客坐下后才去后厨洗菜、切菜,再下锅爆炒,最后端上桌。顾客望着空盘子等了十几分钟,早就没了胃口。前端开发里的SPA(单页应用)正是如此:用户访问网站,浏览器先拿到一个几乎没有内容的HTML骨架,就像空盘子上桌,真正的“菜”——页面内容——要等浏览器下载并执行完一堆JavaScript之后才被“炒”出来。
这种模式叫客户端渲染(Client-Side Rendering,CSR)。页面内容靠浏览器里的JS动态生成,消耗的是用户设备的性能和网络带宽。网络慢一点、手机旧一点,首屏时间就会成倍拉长;更麻烦的是,很多搜索引擎爬虫读不懂白屏骨架里的内容,SEO排名自然吃亏。把CSR的首屏耗时拆成四段,问题就一目了然了:
1. HTML空壳:服务器返回一个只包含根节点的空白HTML文档,浏览器开始解析时页面还是一片空白。
2. JS下载:浏览器需要通过网络下载打包好的JavaScript文件,脚本体积越大下载越慢。
3. JS执行:下载完成后,浏览器要解析、编译并执行JS,这是一个CPU密集型过程,老设备尤其吃力。
4. 渲染:JS调用框架的渲染引擎,把虚拟节点转换成真实DOM,页面内容才真正可见。
回到餐馆的比喻——让顾客干等不仅败好感,还会直接流失客人。CSR的“现点现炒”模式,在用户体验和SEO上都付出了高昂代价,这才催生了SSR和SSG两种新的“出餐方案”。
SSR服务端渲染——后厨实时出菜
既然“现点现炒”让顾客等太久,那试试另一种餐馆的做法:顾客点完菜,后厨立刻开火,用提前备好的食材快速翻炒,几分钟后端上桌的是一盘完整的菜。浏览器请求一个页面时,服务器不再返回空壳,而是在服务器里把组件渲染成完整HTML,再一次性返回给浏览器。这种模式叫服务端渲染(Server-Side Rendering,SSR)。
SSR的关键在于“渲染发生在服务器”。用户请求到达服务器时,服务器执行前端框架的渲染逻辑——读取数据、运行组件、生成HTML字符串——然后把内容完整地送回浏览器。用户看到的不再是白屏,而是已经包含文字和图片的真实页面,首屏体验瞬间提升。这一特性也让爬虫抓取到的HTML直接带正文,SEO效果接近纯静态页面。
SSR的首屏时间主要由三部分构成:
1. 请求往返:浏览器把页面URL发给服务器,网络请求在浏览器和服务器之间走一趟,耗时取决于网络质量。
2. 服务端渲染:服务器执行组件的渲染逻辑,将数据和模板组合成完整的HTML字符串,这是SSR的核心开销。
3. HTML传输:渲染完成的HTML通过网络返回浏览器,浏览器直接解析并显示,不再依赖JavaScript执行。
SSR像“后厨实时出菜”,好处是菜品新鲜、内容实时,坏处是每来一桌客人都要占一个灶台——服务器得实时渲染每个请求,流量一大CPU就吃紧。所以SSR适合登录态强、数据频繁变化的应用,但要注意扩容、缓存和渲染性能优化。
SSG静态生成——预制菜直接上桌
还有一家更极致的餐馆:开店之前就把所有招牌菜做成预制菜,按份封装冷藏。顾客进门,按单取菜,十秒钟就端上桌。静态生成(Static Site Generation,SSG)就是这个思路——在构建阶段就把所有页面渲染成静态HTML文件,然后发布到CDN或静态服务器上,用户访问时直接返回现成文件。
SSG的核心特征是“渲染前置”:把本来在用户请求时的工作,提前到项目构建时完成。部署后,用户的请求不再触发任何服务器计算,CDN边缘节点直接把预先构建好的HTML文件返回浏览器。因为跳过了服务端渲染和JS下载执行等耗时步骤,SSG的首屏速度通常是三种方案里最快的,而且部署成本极低。
SSG首屏的时间模型非常简洁:
1. CDN查找:用户请求从最近的CDN边缘节点查找对应的静态文件,缓存命中时耗时仅几毫秒。
2. HTML传输:静态文件直接从CDN传输给浏览器,途中没有服务器计算和渲染开销,速度取决于网络带宽。
预制菜的代价也很明显:如果菜品要换配方,不能只改一块,得把整批预制菜重新生产——SSG页面内容一变,就需要重新构建、重新部署所有页面。因此SSG适合官网、博客、文档这类内容更新频率低的站点,静态文件越多,出餐效率越高。
性能与SEO对比——三条出品线的账本
现在把三家餐馆的账本摆在一起看。CSR像顾客等厨师现场炒菜,首屏慢、SEO弱,但胜在部署简单、服务器零压力;SSR像顾客点单后厨现做,首屏快、SEO好,但每次请求都要占服务器资源;SSG像预制菜直接上桌,首屏最快、SEO友好,而且几乎没有服务器计算压力。
从SEO的角度看,搜索引擎爬虫抓取页面时,看到的是服务器返回的HTML内容。CSR返回空壳HTML,正文全靠JS后续生成,爬虫往往拿不到内容;SSR和SSG返回的都是含完整正文的HTML,爬虫可以直接提取文字、图片和链接,收录效果自然更好。
1. SSG(≈最高):静态HTML把正文直接内置,对爬虫最友好,收录效果最稳定。
2. SSR(≈最高):请求返回的HTML同样包含完整正文,爬虫抓取效果与SSG接近。
3. CSR(较低):爬虫只能抓到空白骨架,正文不可见,SEO效果明显不如前两者。
在性能方面,SSG首屏最快,SSR次之,CSR最慢;在部署运维方面,CSR最简单(纯静态托管),SSG稍复杂(需要构建步骤),SSR最重(需要常驻Node服务器)。选型本质上是“新鲜度、速度、成本”三者的权衡。
主流框架实践——Next.js与Nuxt.js的“菜单”
餐馆开到连锁店阶段,想在同一家店里既卖预制菜又做现炒菜,就需要一套标准化的“菜单系统”。在前端领域,这套系统就是Next.js和Nuxt.js。它们是主流的全栈框架,允许开发者在同一个项目里,按页面灵活切换SSR与SSG,不必为每个页面单独搭一套技术栈。
在Next.js(React生态)中,SSR和SSG的切换主要由数据获取函数决定。页面组件里导出一个特殊函数,框架就会在对应阶段执行它:如果导出的是getServerSideProps,该页面会在每次请求时执行服务端渲染;如果导出的是getStaticProps,该页面会在构建时预生成静态HTML。两者就像菜单上标注的“现炒”和“预制”两种做法,同一道菜可以按需选择。
1. SSR分支:getServerSideProps接收每个请求的上下文对象,每次访问都会在服务器上执行渲染逻辑,适合数据频繁变化的页面。
2. SSG分支:getStaticProps在构建时读取数据并注入页面,生成静态HTML文件,适合内容相对固定的页面。
Nuxt.js(Vue生态)提供类似能力:nuxt generate 命令生成静态站点,对应SSG;默认的服务端渲染模式则通过Node服务器实时渲染页面,对应SSR。两大框架的选型逻辑完全一致:看页面内容的更新频度,更新频繁的用SSR,长期稳定的用SSG。
ISR混合渲染——定时保鲜的预制菜
预制菜虽快,但放久了不新鲜。如果一家食堂既想保留预制菜的极速出餐,又想保证招牌菜每隔几小时换一批新的,怎么办?聪明的做法是“定时重做”——每隔一段时间重新生产一批预制菜替换旧的。这正对应增量静态再生(Incremental Static Regeneration,ISR)。
ISR在SSG的静态页面上加了“保质期”(TTL,Time To Live)。页面第一次以静态HTML提供服务,TTL计时开始;当TTL到期后,用户请求会触发服务器在后台重新渲染该页面,并把新HTML替换成新的静态版本。访问者可能先看到旧版本,但下一次刷新就能看到新内容,整个过程用户无感知。
1. 旧版HTML:t0时刻生成的静态版本,在TTL有效期内对用户正常响应,保持静态页秒开体验。
2. TTL失效:时间超过设定的有效期后,页面进入“需要刷新”状态,但旧版本仍可服务用户。
3. 后台重建:服务器异步重新获取数据并渲染页面,生成t1时刻的新版本,替换旧版本后TTL重新计时。
ISR非常适合“内容定期变化但不需要秒级实时”的场景,例如新闻列表、商品促销价、活动聚合页——既享受静态页面秒开的极速体验,又不必每次改动都手动重新构建全站。这就像定期更换预制菜,顾客吃到的始终是新做的,但等待时间几乎为零。
AI 应用场景
场景一:企业官网与公司产品介绍页
阶段:前端渲染选型与部署
解决的问题:传统CSR官网首屏白屏时间长,搜索引擎收录差,市场部门费劲做的推广页排名上不去。采用SSG后,页面在构建时一次性生成,所有内容以静态HTML直接部署到CDN,首屏秒开,SEO收录完整。
具体案例:某SaaS公司官网有30多个产品页和博客文章,内容每周更新一次。团队迁移到Next.js并使用getStaticProps预渲染全部页面,配合GitHub Actions自动构建部署,页面加载速度从3.2秒降到0.6秒,自然搜索流量三个月内增长80%。
场景二:电商商品详情页与促销活动页
阶段:服务端实时数据渲染
解决的问题:电商商品页包含实时库存、动态价格、用户个性化推荐,纯SSG无法保证数据实时性。采用SSR(或ISR)后,每次请求都能拿到最新库存和价格数据,同时保留首屏完整HTML,兼顾SEO与实时体验。
具体案例:某垂直电商平台在双十一大促期间,商品详情页用SSR渲染,Redis缓存商品基础信息,服务端渲染耗时稳定在80ms内,扛住了平时5倍流量,搜索结果页还通过ISR每5分钟刷新一次价格。
场景三:新闻资讯与内容门户
阶段:增量更新与内容分发
解决的问题:新闻站点内容每小时都在更新,全量SSG每次重新构建耗时巨大,纯SSR单机吞吐量有限。ISR方案让热门频道每10分钟重新生成一次,普通文章页构建时生成,突发新闻再辅以CSR组件实时加载,实现“快、鲜、省”兼得。
具体案例:某科技媒体用Nuxt.js的ISR能力,对首页和栏目页设置15分钟TTL,正文页用SSG生成。改版后服务器成本下降60%,首页首屏时间从2.5秒降到0.9秒,Google收录速度从3天缩短到2小时。
Python 演示
import random def csr_first_paint(js_size=300): """模拟客户端渲染首屏耗时:空壳HTML + 下载JS + 执行JS + 渲染""" html_empty = 20 js_download = 60 + js_size * 0.1 js_parse = 80 + js_size * 0.05 render = 40 + random.random() * 20 return html_empty + js_download + js_parse + render def ssr_first_paint(server_time=120): """模拟服务端渲染首屏耗时:网络请求 + 服务器渲染 + 返回HTML""" network = 25 server_render = server_time + random.random() * 20 html_transfer = 10 + random.random() * 5 return network + server_render + html_transfer def ssg_first_paint(cdn_latency=8): """模拟静态生成首屏耗时:CDN查找 + 返回HTML""" cdn_search = 3 + random.random() * 3 html_transfer = cdn_latency + random.random() * 5 return cdn_search + html_transfer if __name__ == "__main__": samples = 5 csr_times = [csr_first_paint() for _ in range(samples)] ssr_times = [ssr_first_paint() for _ in range(samples)] ssg_times = [ssg_first_paint() for _ in range(samples)] print("渲染方案首屏耗时模拟(单位:毫秒,取5次平均)") print(f"CSR: {sum(csr_times) / samples:7.1f} ms") print(f"SSR: {sum(ssr_times) / samples:7.1f} ms") print(f"SSG: {sum(ssg_times) / samples:7.1f} ms")
def csr_first_paint(js_size=300)定义CSR耗时函数,包含HTML空壳、JS下载、JS执行和渲染四段耗时,跟正文公式一一对应。js_download = 60 + js_size * 0.1模拟JS体积越大、下载耗时越长的线性关系。def ssr_first_paint(server_time=120)定义SSR耗时函数,包含请求往返、服务端渲染和HTML传输三段。server_render = server_time + random.random() * 20模拟服务器渲染时间的不稳定性,这也是SSR在高负载下性能波动的根源。def ssg_first_paint(cdn_latency=8)定义SSG耗时函数,只需CDN查找和文件传输,开销最小。csr_times = [csr_first_paint() for _ in range(samples)]每种方案各采样5次,减少随机波动的影响。print(f"CSR: {sum(csr_times) / samples:7.1f} ms")输出格式化结果,让三种方案的耗时对比一目了然。
常见误区
误区“SSG和SSR差不多吧?SSG只是把SSR做得更快一点,本质都是服务端渲染。”我刚接触时也这么以为,直到发现SSG页面更新不上来才知道不对劲。
正解两者执行时机完全不同。SSR是在每次用户请求时由服务器实时渲染,SSG是在构建阶段提前生成静态文件。SSG快是因为它把渲染工作提前完成了,代价是内容更新需要重新构建;SSR慢是因为它每个请求都要现算,代价是服务器压力大。就像“预制菜”和“现炒菜”,虽然都是后厨出来的菜,但一个提前做好,一个客到了才做。
为何常见:SSR和SSG都能返回完整HTML,对浏览器和爬虫的效果相似,新手容易只看到表象,忽略“何时生成”这个关键区别。
误区“SSR把完整HTML返回给爬虫了,SEO就万事大吉,标题、描述、关键词都可以随便写。”有些团队用了SSR后反而SEO没涨。
正解SSR只是解决了“爬虫能看到内容”这个基础问题,SEO还包括页面标题、meta描述、Open Graph标签、结构化数据、URL结构、内链布局等一系列工作。SSR让爬虫能读到你写的HTML,但你写的内容质量、关键词布局、页面权重才是排名真正的决定因素。这就像餐馆从“外卖打包”(CSR)升级到“堂食摆盘”(SSR),菜端上桌了,但好不好吃才是顾客给不给好评的关键。
为何常见:因为SSR号称“SEO友好”,很多人把它理解为“用了就SEO满分”,忽略了SEO是一个系统工程。
误区“SSG生成的是静态文件,所以页面上不能有任何动态数据,只能做纯展示页面。”有同事因此把所有需要展示最新数据的页面都改成SSR。
正解SSG页面完全可以包含动态内容,关键在于动态部分的实现方式:可以配合客户端请求在浏览器端拉取数据(CSR局部),也可以用ISR定期重新生成页面保证内容新鲜,还可以用服务端组件等方式按需注入。SSG不等于“死页面”,它更像预制菜,出厂后也能配上新鲜酱料(客户端数据)或者定期回锅(ISR)。
为何常见:把“生成时机”和“数据来源”两个维度搞混了。SSG只决定页面在构建时生成,并不限制页面运行后的交互和数据获取。
误区“一个项目要么全用SSR,要么全用SSG,不能混着用,否则架构会乱。”小团队常为选哪个吵得不可开交。
正解现代框架(Next.js、Nuxt.js等)支持页面级渲染策略,一个项目里完全可以按路由划分:官网首页和博客文章用SSG,订单中心和用户后台用SSR,商品列表用ISR定期刷新。判断标准是每个页面的内容更新频率、SEO需求和实时性要求。这就像同一家餐馆,招牌菜可以预制,客点菜可以现炒,两种模式共存而不冲突。
为何常见:传统多页应用时代,每个项目只能选一种技术栈,这个思维惯性延续到了渲染方案上。其实框架早就在架构层面支持了混合渲染。
面试题
Q1. SSG的英文全称是什么?
- A.服务端渲染
- B.静态站点生成← 正确答案
- C.客户端渲染
- D.增量静态再生
答案:B。SSG全称Static Site Generation,静态站点生成,核心是在构建时把页面生成为静态HTML文件。服务端渲染是SSR,客户端渲染是CSR,增量静态再生是ISR,三者的英文缩写对应不同的渲染模式。
Q2. CSR首屏白屏时间长的主要原因是?
- A.服务器渲染耗时太长
- B.浏览器需要等待JS下载执行← 正确答案
- C.后端接口返回数据过慢
- D.CDN缓存未命中
答案:B。CSR首屏要经历“下载空壳HTML → 下载JS → 执行JS → 渲染DOM”四个阶段,其中等待JS下载和执行是最主要的耗时来源。这就像顾客点菜后要等厨师从买菜开始做起,环节多自然慢。
Q3. SSG构建完成后,最终产出什么?
- A.静态HTML文件← 正确答案
- B.动态JavaScript脚本
- C.数据库查询结果
- D.服务器端API接口
答案:A。SSG在构建阶段就把页面渲染成静态HTML文件,发布到CDN后用户直接访问这些文件。它不需要数据库查询,也不需要常驻服务器执行JS,这是它响应快、成本低的根本原因。
Q4. 相比CSR,SSR最大的变化是什么?
- A.渲染工作由服务器完成← 正确答案
- B.渲染工作由客户端完成
- C.渲染不需要任何代码参与
- D.渲染改由数据库完成
答案:A。SSR把组件渲染从浏览器端搬到了服务器端,用户请求时服务器直接返回完整HTML。这就像“现炒菜”从顾客面前搬到了后厨完成,顾客看到的直接是成品,而不是一堆半成品原料。
Q5. 以下哪些属于SSR的缺点?
- A.服务器压力明显增大← 正确答案
- B.每个请求都要实时计算← 正确答案
- C.静态资源无法使用缓存
- D.部署运维复杂度较高← 正确答案
答案:ABD。SSR每个请求都要占用服务器CPU执行渲染,并发上来后压力很大,部署时也需要常驻Node服务,运维成本高于纯静态方案。但JS、CSS等静态资源依然可以通过CDN缓存,所以C不正确。
Q6. 下列哪些场景更适合使用SSG?
- A.内容稳定、不频繁改版的官网← 正确答案
- B.不需要登录即可阅读的博客← 正确答案
- C.每用户高度个性化的推荐页面
- D.更新频率较低的商品详情页← 正确答案
答案:ABD。SSG适合内容稳定、更新频率低的页面。官网、博客、低频改版的商品页都是典型场景。个性化推荐依赖每个用户的实时数据,用SSG无法覆盖,更适合CSR或SSR。
Q7. Next.js中实现SSG应使用哪个函数?
- A.getServerSideProps
- B.getStaticProps← 正确答案
- C.componentDidMount
- D.useEffect钩子
答案:B。Next.js中getStaticProps在构建时执行并生成静态页面,对应SSG;getServerSideProps在每次请求时执行,对应SSR。componentDidMount和useEffect都是React客户端的生命周期函数,和构建时数据获取无关。
Q8. ISR更新页面的工作机制是什么?
- A.每次用户请求都触发服务器重新渲染
- B.TTL过期后在后台异步重新生成页面← 正确答案
- C.用户在浏览器端手动刷新触发更新
- D.构建系统自动删除所有旧页面文件
答案:B。ISR的静态页面设有TTL(保质期),过期后用户请求会触发后台异步重建新页面并替换旧版本。重建过程中旧页面仍可正常访问,用户无感知。A是SSR的机制,C和D都不属于ISR。
Q9. 选择渲染方案时需要综合考量哪些因素?
- A.内容更新频率← 正确答案
- B.SEO需求强弱← 正确答案
- C.服务器预算成本← 正确答案
- D.页面字体加载方式
答案:ABC。内容更新频繁选SSR或ISR,更新慢选SSG;SEO需求高应避免纯CSR;服务器预算是SSR的主要成本约束。字体加载方式属于前端性能优化范畴,与渲染方案选型关系不大。
Q10. 混合渲染模式(SSG + SSR/ISR)的核心优势是什么?
- A.既保留静态页极速响应,又能按需更新内容← 正确答案
- B.只提升服务端渲染速度而不改变内容
- C.彻底避开SEO技术细节无需优化
- D.让所有计算都在客户端完成
答案:A。混合渲染让稳定的页面用SSG秒开,变化快的页面用SSR/ISR保障实时性,同一项目内各取所长。它并不能完全替代SEO工作(B、C错误),也不是把计算挪到客户端(D错误),而是按页面粒度做最优组合。