web性能-首屏时间详解及优化

3,158 阅读7分钟

web性能-白屏时间详解以及优化

简单理解:用户打开浏览器输入网站的URL后,从屏幕空白到第一个画面出来的时间

  • 这个时间的长短将直接决定网站页面给用户的第一印象
  • 在谷歌的PageSpeed Insights内,是 FCP(First Contentful Paint)

白屏过程详解

上图可以看到:浏览器和服务器做了哪些交互,又在客户端做了哪些

white-screen.png

接下来以此介绍每个步骤

1. DNS Lookup (DNS查询)

浏览器从DNS服务器中进行域名查询,获取IP地址后,才能与服务端通信

  • 访问一个网站可能会有多次,因为一些是 CDN资源 或 异源静态资源

对大中型网站来说,通常在页面加载过程中会产生下列域名解析:

  • www.example.com 页面URL本身。
  • style.example.com,JS、CSS等静态资源请求。
  • img.example.com,静态图片请求。
  • ajax.example.com,各种站内的Ajax请求。
  • *.google.com,其他比如Google的站外请求。

域名解析的过程,可短至几十毫秒,也可能消耗几秒,所以解析过程的快慢直接影响页面整体加载的渲染速度,特别是对于每天访问量达千万级别的页面

DNS一旦出现问题,对用户体验的影响是非常大的

  • 如果DNS Lookup时间过长会引起白屏时间过长。图片的话,会白图时间过长

DNS解析速度的优化策略有很多,通常我们会从以下几个方面思考细节的优化:

  • DNS预加载策略
  • DNS缓存优化。
    • 设置合理的缓存时间
  • 页面中资源的域名的合理分配。
    • 减少一个新域名,就能减少一次DNS Lookup
  • 稳定可靠的DNS服务器等。

2. 建立TCP请求连接

浏览器针对各个域名进行DNS Lookup得到IP地址后,就开始建立TCP请求连接的过程。

TCP通过三次握手建立连接,并提供可靠的数据传输服务。

优化参考:

  1. 尽量将操作系统进行版本升级。
    • 高版本的Linux操作系统对TCP内核进行了多项优化,包括拥塞窗口变大、EarlyTransmit等算法优化。
  2. 尽量通过监控工具发现问题,例如LastMile。
    • 远距离的传输容易丢包,可以通过LastMile来发现问题。在建立连接的时候丢包,为了避免定时器溢出再进行报文的传输,可以通过调整初始RTO来减少网络耗时。
  3. 用户体验要注意 RTO。
    • RTO (Recovery Time Objective,复原时间目标)是企业可容许服务中断的时间长度
    • 服务器端耗时占用整体耗时的一小部分,要把主要精力放在网络耗时的减少上。如果是小型网站,服务的用户群相对比较集中,就不要考虑 TCP 优化,因为带来的收益往往很小。
  4. 尽量减小HTTP报文的大小。
    • 因为HTTP报文越小,传输所需要的RTT((Round-Trip Time 往返时延)次数越少,耗时越短,通常Ajax异步化是减少HTTP同步报文大小的主要手段。
  5. 尽量减少HTTP头的大小。
    • HTTP的Gzip压缩只针对HTTP主体,而HTTP头是不能被压缩的,要尽早对Cookie大小进行控制,因为Cookie往往是造成HTTP头偏大的主要因素,Cookie大小在很多时候都接近4KB的上限。
  6. 尽量将机房部署在离核心用户近的地方。
    • 通过减少网络距离来减少网络耗时。
  7. 尽量选择大的运营商。
    • 小的运营商往往在BGP选路时会绕路,造成网络耗时增加。

具体细节可看博主姊妹骗:TCP传输基本原理简述及优化

3. 服务端请求处理响应

在TCP连接成功建立后,Web服务器接受请求,开始请求处理,而浏览器端则开始等待服务器的处理响应

服务端完成请求处理,开始响应客户端内容(在Web页面中,客户端的角色主要由浏览器来扮演),即开始了在前端由浏览器显示页面的过程

服务端的请求处理速度优化

是一个非常复杂的专题,它涵盖的范围非常广,并且对于不同的网络平台,也有不一样的优化策略。

对于中小型网站来说,重心可能主要放在数据获取过程的优化。

  • 其中对缓存、数据库等处理的优化,可为网站页面带来较大的响应速度提升。

对于有着亿级流量的大型网络平台,每一个过程的优化都可能带来质的提升。

  • 比如被很多人忽略的模板渲染过程,通过优化模板渲染逻辑,可使模板渲染速度提高一倍;
  • 或者通过调整Gzip算法及响应内容的代码结构,来提高Gzip压缩率、减小压缩包大小等

4. 客户端下载、解析、渲染显示页面

服务器返回HTTP Response后,浏览器陆续开始接收数据,进行HTML下载、解析、渲染显示等过程。

具体步骤如下:

  1. 如果是Gzip包,则先解压为HTML。
  2. 解析HTML的头部代码,下载头部代码中引用的样式资源文件或者脚本资源文件。
  3. 解析HTML代码和样式文件代码,这个过程会构造出两个树结构,即与HTML相关的DOM树,以及与CSS相关的CSSOM树。
  4. 通过遍历DOM树和CSSOM树,浏览器依次计算每个节点的大小、坐标、颜色等样式,构造出渲染树。
  5. 根据渲染树完成绘制的过程。

而在真实页面解析过程中,浏览器通常会因为各种因素被阻断。

  1. HTML代码中的JavaScript代码(简称JS代码)会阻断DOM树的构造
    • 因为浏览器认为这段JS代码可能会修改DOM结构,所以必须等待JS代码执行完毕,再恢复DOM树的构造过程。这是由浏览器的安全解析策略决定的
  2. 浏览器必须等待样式表加载完成,才能开始构建CSSOM树。
  3. 还有一种特殊情况,浏览器在解析HTML时遇到JS代码,而此时CSSOM树还未构建完成,则浏览器会暂停脚本的执行
    • (浏览器同时也会暂停继续向下解析HTML代码,从而导致DOM树的构建过程被暂停阻塞),直到CSS样式文件下载完成,并完成CSSOM树的构建,才会重新恢复原来的解析。这也是由浏览器的安全解析策略决定的。

详细的标签对于dom解析的影响,可以参考博主的姊妹篇和和dom解析渲染之间的关系

通过对上面各因素的分析,我们可以发现,HTML中的内联JS代码执行的危害之处,不在于它阻断了 DOM 树的构建过程,除非是一段特别恶劣的 JS 代码运行非常慢。

  • 通常内联的 JS代码运行大概消耗几十毫秒,也就是暂停构建几毫秒到几十毫秒。
  • 它最大的危害在于上面第三种情况提到的,即DOM树构建被阻塞的时间不是只有JS代码运行的时间,而是会加上样式资源文件下载和CSSOM 树的构建时间,这时浏览器所进行的串行解析过程,与我们在前面期望的DOM树和CSSOM树的并行解析过程相差甚远。

过程图:

dom.png

优化策略:

根据渲染步骤,大概可以从以下几个方面着手:

  1. 优化HTML代码和结构,缩短HTML下载时间,加快HTML解析速度。
  2. 优化CSS文件和结构,缩短CSS文件下载时间和解析时间。
  3. 合理优化Js代码。并合理放置JS代码,避免前面第三种情况的出现,这也是最重要的。

具体的优化可以参考 博主的姊妹篇:


部分参考丛书《大型网站性能优化实战:从前端、网络、CDN到后端、大促的全链路性能优化详解》