/ 前端

记一次基于nextjs的ssr项目知识储备

第一次实打实的接触ssr,针对在该项目中遇到了一些列的问题记录

前期储备
  1. 了解一下从输入url到页面加载的过程 (参考
  2. http协议(主要了解响应体,请求体)
  3. node的一些知识储备(koa、middleware、koa-router等等等等...)
  4. session与cookie的区别
正题

为什么要使用ssr,相对于csr带来的好处是什么呢?

  1. 服务端渲染首先会在服务端获取到渲染页面的数据,然后拼装需要渲染的 HTML 数据,最后发送到客户端。客户端在拿到这些初始化的页面 HTML 和 所需要的数据后渲染页面。他解决了初始化页面慢的问题,不需要等待 javascript 加载好才能看到页面。
  2. 由于数据和标签在首次加载时候都由服务端进行提供了,所以搜索引擎爬虫是可以成功或许到 HTML body 的。即使用户在浏览器禁用了 javascript,我们的页面也能够正常显示。它解决了 SEO 问题。

正是因为SSR拥有这些优点,而我司产品,面向的又是消费者,这才让我们下定决心(对页面)使用服务端渲染。不过第一次把技术栈切到React和Nodejs的时候,才发现SSR性能的优化工作(其实)也花了我们很多时间和精力。(为啥呢)?这是因为SSR性能优化的一部分工作是针对首屏渲染的优化,(忘记说了),首屏渲染(above-the-fold render)也是我们衡量性能的重要指标之一。


ssr跟csr的区别(上图)

1-jJkEQpgZ8waQ5P-W5lhxuQ

1-CRiH0hUGoS3aoZaIY4H2yg

从图中可以看出,(这两种渲染方式的)区别主要在于出现首屏渲染的时机。对于SSR来说,服务器返回的是(结构相对完整的)HTML文件,(通过解析HTML文件),浏览器就能渲染出页面。而对CSR来说,浏览器拿到的只是包含JavaScript代码的HTML文件,(换句话,在浏览器渲开始渲染出页面之前,需要动态创建HTML标签)。这也就意味着,SSR可以让浏览器在边下载JavaScript文件的同时边渲染HTML页面,换句话说,浏览器再也不需要等到所有的JavaScript文件下载并执行完之后才去渲染页面啦。(译者注:上述方式属于增量式构建),从SSR以及CSR的时序图里,我们可以发现,这两种渲染方式还是有蛮多共同点的:

  • 都需要下载React的
  • 都需要经历虚拟DOM构建过程
  • 都需要(给页面元素)绑定事件来增强页面的可交互性
    不过对于使用SSR方式渲染出的HTML页面来说,用户是可以在这些操作(指的是下载React、构建虚拟DOM、绑定事件)完成之前就能看到页面。再反观使用CSR方式渲染出的HTML页面,你必须等到上面的这些操作(指的是下载React、构建虚拟DOM、绑定事件)都完成,virtual-dom转换成(浏览器)页面上的真实dom之后,用户才能看到页面。

使用SSR渲染的另一大优势(Another Bonus):(熟悉浏览器渲染机制的人都应该知道),使用CSR渲染的话,页面很容易白屏。相反,如果你使用SSR渲染的话,白屏就不(那么)容易出现啦。尽管大家都知道,使用CSR(在很大程度上)就意味着页面白屏,不过大多数人还是会使用下面的这种方式来规避(白屏)风险(在服务器返回所有数据之前,给页面添加loading图,然后在所有数据到达之后,把loading图撤掉)。(译者注:用砖业术语是酱紫描述的,在数据到达之前,让页面开始转“菊花”,数据到达之后,移除“菊花”图)

前方高能预警(there are a few caveats),请所有(使用SSR方式)的小伙伴提前做好战斗准备:

  • 虽说使用SSR方式渲染,不但可以让浏览器更早的渲染出HTML页面,而且还能让用户更快的看到HTML页面。不过美中不足的是,在React没有执行之前,这些页面是不存在交互这一说的,甚至是包括像用户(快速)点击按钮等类似(这样简单)的交互都不能完成。

  • (熟悉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具有以下特点:

  • 同步方法

  • 会阻塞(hold)整个事件循环流程

(换句话说),在ReactDOMServer.renderToString没有执行完之前,服务器是(绝)不可能处理其它请求的。(啥?你说我讲的太抽象啦,完全听不懂),(那好吧,不妨)让我们做个假设(Let’s say ),在使用SSR渲染HTML页面的过程中,执行ReactDOMServer.renderToString就花了500ms,这意味你现在每秒最多只能处理两个请求。(如果有同学对这方面感兴趣的话,可以重点关注一下)


说了这么多理论储备,再看看实际情况

ssr
89D60AA7-D506-440B-974A-606B59EC1775

csr
70960360-32C0-469D-BC2E-43E8401DB76C


后续优化方案
因我司的产品流量是有峰值的,所以在峰值较高的时间点让其切换到csr,其他平稳阶段使用ssr
具体可参考

记一次基于nextjs的ssr项目知识储备
Share this