(先交代一下背景),咱们walmart(沃尔玛)主站的(大)多数页面,使用的是服务端渲染(如下用简称SSR代替),只有极个别页面使用的是客户端渲染。html
咱们之因此使用服务端渲染,正是基于如下两个缘由:react
在用户购物的过程当中,可以让用户享受到页面性能(的)提高所带来的用户体验web
符合(consistent)咱们对页面SEO性能优化的要求chrome
正是由于SSR拥有这些优势,这才让咱们下定决心(对页面)使用服务端渲染。(不过,说实话),当咱们(真的)把技术栈切到React和Nodejs的时候,(吃惊的发现),SSR性能的优化工做(其实)也花了咱们不少时间和精力。(为啥呢)?这是由于SSR性能优化的一部分工做是针对首屏渲染的优化,(忘记说了),首屏渲染(above-the-fold render)也是咱们衡量性能的重要指标之一。(顺道安利一下)咱们本身的开源框架Electrode framework,该框架内置了多个有助于SSR性能提高的独立模块,(若是没记错的话),我以前就写过有关于使用这些模块所带来性能提高的介绍。浏览器
Eletrode框架(旨在解决SSR性能优化问题)一经发布,不久我就收到了许多有关于使用SSR(究竟)能带来(哪些)好处的提问以及相关的评论。大家如今看的这篇文章,主要讲的是使用SSR(究竟)能带来(哪些)好处,至于SEO优化(究竟)能带来(哪些)好处等话题,(我以为)Andrew Farmer和Patrick Hund他俩的文章已经讲得很全面啦,(我这里将再也不赘述)。性能优化
接下来,我将会用最直观(super simple)的时序图(timeline diagram)来阐述SSR以及CSR之间的区别。服务器
从图中能够看出,(这两种渲染方式的)区别主要在于出现首屏渲染的时机。对于SSR来讲,服务器返回的是(结构相对完整的)HTML文件,(经过解析HTML文件),浏览器就能渲染出页面。而对CSR来讲,浏览器拿到的只是包含JavaScript代码的HTML文件,(换句话,在浏览器渲开始渲染出页面以前,须要动态建立HTML标签)。这也就意味着,SSR可让浏览器在边下载JavaScript文件的同时边渲染HTML页面,换句话说,浏览器不再须要等到全部的JavaScript文件下载并执行完以后才去渲染页面啦。(译者注:上述方式属于增量式构建),从SSR以及CSR的时序图里,咱们能够发现,这两种渲染方式仍是有蛮多共同点的:网络
不过对于使用SSR方式渲染出的HTML页面来讲,用户是能够在这些操做(指的是下载React、构建虚拟DOM、绑定事件)完成以前就能看到页面。再反观使用CSR方式渲染出的HTML页面,你必须等到上面的这些操做(指的是下载React、构建虚拟DOM、绑定事件)都完成,virtual-dom转换成(浏览器)页面上的真实dom以后,用户才能看到页面。app
使用SSR渲染的另外一大优点(Another Bonus):(熟悉浏览器渲染机制的人都应该知道),使用CSR渲染的话,页面很容易白屏。相反,若是你使用SSR渲染的话,白屏就不(那么)容易出现啦。尽管你们都知道,使用CSR(在很大程度上)就意味着页面白屏,不过大多数人仍是会使用下面的这种方式来规避(白屏)风险(在服务器返回全部数据以前,给页面添加loading图,而后在全部数据到达以后,把loading图撤掉)。(译者注:用砖业术语是酱紫描述的,在数据到达以前,让页面开始转“菊花”,数据到达以后,移除“菊花”图)框架
前方高能预警(there are a few caveats),请全部(使用SSR方式)的小伙伴提早作好战斗准备:
(熟悉HTTP协议的人都应该知道),在使用SSR方式渲染HTML页面的过程当中,浏览器获取第一个字节的时间(Time To First Byte)要长于用CSR渲染HTML页面所获取的时间,(为啥呢)?这是由于在你使用SSR方式渲染页面的过程当中,你服务器须要花更多的时间来渲染出(浏览器所须要的)HTML结构,(最后才将渲染好的HTML结构做为响应返回),而不像CSR那样,服务器只须要返回字节相对较少的Json数据(relatively empty respons)。
(经过对比SSR、CSR这两种渲染方式,你会发现),在使用SSR方式渲染HTML页面的过程当中,服务器的吞吐量会明显少于用CSR渲染HTML页面时服务器的吞吐量。尤为是当你在服务端使用react的时候,(你会发现,是否使用react的服务端渲染特性,服务器吞吐量每每也是咱们考虑的因素),这是由于react对服务器吞吐量的影响太大啦(the throughput impact is extremely large)。ReactDOMServer.renderToString
具备如下特色:
同步方法
(属于CPU独享型),在调用过程当中,会绑定CPU
会阻塞(hold)整个事件循环流程
(换句话说),在ReactDOMServer.renderToString
没有执行完以前,服务器是(绝)不可能处理其它请求的。(啥?你说我讲的太抽象啦,彻底听不懂),(那好吧,不妨)让咱们作个假设(Let’s say ),在使用SSR渲染HTML页面的过程当中,执行ReactDOMServer.renderToString
就花了500ms,这意味你如今每秒最多只能处理两个请求。(若是有同窗对这方面感兴趣的话,能够重点关注一下)
(接下来,我将会带着你们来亲身感觉一下,咱们walmart主站是如何在生产环境实践SSR以及CSR的),如下是咱们针对SSR、CSR这两种渲染方式所作的一些对比。
为了(更好的)对比SSR、CSR这两种渲染方式,咱们分别拿出了(walmart主站的)home、category以及search三个模块来进行对比。(忘记说了),当前的这张图片以及接下来的图片都是咱们在页面进行渲染的过程当中,使用chrome(浏览器自带的Screenshots工具)所抓取的快照。(译者注:此处应该有掌声),经过查看图片,你会发现使用SSR的话,HTML页面渲染更快,相反使用CSR的话,HTML页面在加载过程当中会出现白屏。虽然说绝大多数应用仍是能够经过(显式地使用)loading图的方式来解决页面白屏,不过咱们的作法是酱紫的:在常规状况下,咱们会使用SSR方式,(不过一旦 生产环境出现紧急状况),须要强制切到CSR的状况下,页面仍是会出现白屏。请注意,虽然说上面的图片只是(对HTML页面渲染状况的)一次快照,(不过你们应该不用担忧),由于咱们天天都会按期在不一样的时间点、不一样的生产环境来跑咱们的机器,因此说咱们获得的个体样本数据很是全(vary-but),(全到啥子程度呢)?你均可以从这些数据中看出app接下来的性能走势啦。
咱们能够看到,(在分别使用SSR、CSR这两种渲染方式的状况下),服务器会针对home、category以及search页面返回相对应的响应头数据。不过我会绿色bar忽略掉,这是由于在网络拓扑图(network graph)当中,(咱们发现),相比绿色bar位置以外的数据来讲,绿色bar所反映出的数据更具备相对性(more relative)。(在这些数据当中),我比较关注的是文件大小以及TTFB。既然服务器会针对不一样的页面返回相对应的HTML,(那么你就有可能注意到),使用SSR方式渲染出的HTML体积老是比用CSR方式大。另一点就是关于服务器的响应速度,(通过咱们测试发现),使用CSR方式,可以让服务器更快地响应页面请求(因为其它缘由,在请求home page页面的过程当中,服务器响应的速度反而变慢啦)。
我不能彻底保证上述结论的正确性,这是由于上述结论掺杂了不少不稳定的因素好比网络是否延迟,服务器是否正常,访问者的地理位置以及其它因素。因此但愿你们不要把上述结论理解为真理(scientific fact),更多的是把它理解为对SSR以及CSR这两种渲染方式趋势的一种解读。
当咱们分别对CSR、SSR这两种渲染方式进行A/B测试时,发现(咱们看到的)结果和以前预期的同样,另外咱们的统计数据显示,渲染的越早,用户的参与度就会越高。
正是基于以上缘由,咱们才决定把开源electrode平台的关注点放在SSR上。electrode默认开启SSR,另外咱们有一些模块是围绕优化SSR展开的。在另一篇文章中,我将会为你们展现,如何使用这两个模块,将RenderToString()的时间缩减至30%。