SSR与CSR对比:渲染定义、核心差异及相关技术问题解答
先搞懂语境里的「渲染」和「编译」到底指什么
你最开始对渲染的认知偏差,是很多人刚接触这俩概念都会踩的坑:
- 你理解的「计算机解析HTML把内容画到屏幕上」,是浏览器层面的最终绘制环节,这步不管CSR还是SSR,最后都是在用户的浏览器、用户的屏幕上完成的,服务端根本不需要接显示器干这个事。
- 我们聊SSR/CSR时提到的渲染,特指「把组件代码、业务数据拼接成可被浏览器解析的完整HTML结构字符串」的过程——谁来做这步拼接工作,就是谁在渲染。
- 而编译是发生在构建环节的前置动作:不管是React的JSX语法、还是Next.js的服务端组件语法,浏览器和Node环境本身都识别不了,编译就是用swc、babel这类工具,把这些特殊语法转换成普通可执行的JS代码、静态模板的过程,你跑
npm run build、本地开发时触发热更新时干的就是这个活,和用户发请求时的渲染动作完全是两个阶段的事。
为什么纯CSR的SPA SEO不好?
你之前的疑惑点本质上是没搞清楚爬虫的工作逻辑:
用Create React App构建的纯SPA,build完生成的入口index.html本质是个空壳——你可以自己打开build产物看一眼,或者上线后右键查看网页源代码,body里基本只有一个<div id="root"></div>,剩下全是引JS包的script标签,没有任何你写在组件里的实际业务内容。
用户访问或者爬虫爬取的时候,服务端直接把这个空壳返回回去。浏览器要等所有JS包下载、解析、执行完成后,React才会在客户端跑起来,把各个组件对应的DOM拼接好塞到root节点里,这时候才能看到实际内容。
而绝大多数搜索引擎爬虫抓页面时,不会等你把JS全下完、执行完再提取内容:很多爬虫拿到初始的HTML响应就直接开始解析内容了,空壳里啥有效信息都没有,自然SEO表现差。哪怕你SPA后续切页不需要发请求、资源一次性加载完,这些动作都是要等JS执行完才会发生,爬虫根本等不到这一步,和你后续交互顺不顺没有关系。现在哪怕谷歌爬虫支持执行JS抓内容,渲染JS会额外消耗爬虫算力,对应页面的搜索权重也会受影响,更别说百度这类对JS渲染支持很差的搜索引擎了。
CSR(React SPA)和SSR(Next.js 传统SSR模式)的核心差异
两者最本质的区别就是「拼接HTML结构」这个渲染动作发生的位置不一样,顺着流程走差别非常清楚:
- 纯CSR流程:
- 构建阶段编译出所有前端JS包,服务端只需要托管静态的空壳HTML和JS、CSS等静态资源
- 用户发请求,服务端直接返回空壳HTML
- 浏览器下载空壳HTML,再下载所有需要的JS资源,执行JS完成渲染,把内容塞到页面里,再绑定所有交互事件
- 后续页面切换完全在客户端完成,不需要再请求服务端拿HTML
- 传统SSR流程:
- 构建阶段会做同构编译:把同一套React代码分别编译成能在Node服务端运行的版本、和能在浏览器运行的客户端版本
- 用户发请求,服务端当场运行对应页面的组件代码,拉取该页面需要的业务数据,直接拼接出带完整实际内容的HTML字符串,返回给浏览器
- 浏览器拿到HTML就可以直接解析、把内容绘制到屏幕上,不需要等JS加载完就能看到内容;之后浏览器再下载客户端JS,给已经存在的DOM绑定交互事件(这个过程叫水合/hydration),水合完成后页面就能响应用户的点击、输入等操作
- 后续页面切换可以根据配置,选择在客户端完成跳转,或者重新请求服务端拿新页面的HTML
顺着流程就能总结出直接的体验和架构差异:
- 首屏性能:SSR首屏白屏时间更短,不需要等大JS包下载执行完就能看到内容;CSR如果JS包体积大、网络差,白屏时间会很长
- SEO表现:SSR返回的初始HTML就带完整内容,爬虫不需要执行JS就能拿到所有信息,SEO友好度远高于纯CSR
- 服务端压力:CSR的渲染压力全在用户的设备上,服务端只需要托管静态文件,并发承载能力强;SSR每次请求都要在服务端跑组件、拼HTML,高并发场景下服务端压力会大很多
- 开发限制:SSR因为组件要在服务端运行,不能直接用
window、document这类浏览器专属API,开发时要做环境判断;纯CSR就没有这个限制。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

