web性能-白屏时间详解以及优化
简单理解:用户打开浏览器输入网站的URL后,从屏幕空白到第一个画面出来的时间
- 这个时间的长短将直接决定网站页面给用户的第一印象
- 在谷歌的PageSpeed Insights内,是 FCP(First Contentful Paint)
白屏过程详解
上图可以看到:浏览器和服务器做了哪些交互,又在客户端做了哪些
接下来以此介绍每个步骤
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预加载策略
- 博主的姊妹篇:juejin.cn/post/694391… (可搜索查看 preconnect 部分)
- DNS缓存优化。
- 设置合理的缓存时间
- 页面中资源的域名的合理分配。
- 减少一个新域名,就能减少一次DNS Lookup
- 稳定可靠的DNS服务器等。
2. 建立TCP请求连接
浏览器针对各个域名进行DNS Lookup得到IP地址后,就开始建立TCP请求连接的过程。
TCP通过三次握手建立连接,并提供可靠的数据传输服务。
优化参考:
- 尽量将操作系统进行版本升级。
- 高版本的Linux操作系统对TCP内核进行了多项优化,包括拥塞窗口变大、EarlyTransmit等算法优化。
- 尽量通过监控工具发现问题,例如LastMile。
- 远距离的传输容易丢包,可以通过LastMile来发现问题。在建立连接的时候丢包,为了避免定时器溢出再进行报文的传输,可以通过调整初始RTO来减少网络耗时。
- 用户体验要注意 RTO。
- RTO (Recovery Time Objective,复原时间目标)是企业可容许服务中断的时间长度
- 服务器端耗时占用整体耗时的一小部分,要把主要精力放在网络耗时的减少上。如果是小型网站,服务的用户群相对比较集中,就不要考虑 TCP 优化,因为带来的收益往往很小。
- 尽量减小HTTP报文的大小。
- 因为HTTP报文越小,传输所需要的RTT((Round-Trip Time 往返时延)次数越少,耗时越短,通常Ajax异步化是减少HTTP同步报文大小的主要手段。
- 尽量减少HTTP头的大小。
- HTTP的Gzip压缩只针对HTTP主体,而HTTP头是不能被压缩的,要尽早对Cookie大小进行控制,因为Cookie往往是造成HTTP头偏大的主要因素,Cookie大小在很多时候都接近4KB的上限。
- 尽量将机房部署在离核心用户近的地方。
- 通过减少网络距离来减少网络耗时。
尽量选择大的运营商。
- 小的运营商往往在BGP选路时会绕路,造成网络耗时增加。
具体细节可看博主姊妹骗:TCP传输基本原理简述及优化
3. 服务端请求处理响应
在TCP连接成功建立后,Web服务器接受请求,开始请求处理,而浏览器端则开始等待服务器的处理响应
服务端完成请求处理,开始响应客户端内容(在Web页面中,客户端的角色主要由浏览器来扮演),即开始了在前端由浏览器显示页面的过程
服务端的请求处理速度优化
是一个非常复杂的专题,它涵盖的范围非常广,并且对于不同的网络平台,也有不一样的优化策略。
对于中小型网站来说,重心可能主要放在数据获取过程的优化。
- 其中对缓存、数据库等处理的优化,可为网站页面带来较大的响应速度提升。
对于有着亿级流量的大型网络平台,每一个过程的优化都可能带来质的提升。
- 比如被很多人忽略的模板渲染过程,通过优化模板渲染逻辑,可使模板渲染速度提高一倍;
- 或者通过调整Gzip算法及响应内容的代码结构,来提高Gzip压缩率、减小压缩包大小等
4. 客户端下载、解析、渲染显示页面
服务器返回HTTP Response后,浏览器陆续开始接收数据,进行HTML下载、解析、渲染显示等过程。
具体步骤如下:
- 如果是Gzip包,则先解压为HTML。
- 解析HTML的头部代码,下载头部代码中引用的样式资源文件或者脚本资源文件。
- 解析HTML代码和样式文件代码,这个过程会构造出两个树结构,即与HTML相关的DOM树,以及与CSS相关的CSSOM树。
- 通过遍历DOM树和CSSOM树,浏览器依次计算每个节点的大小、坐标、颜色等样式,构造出渲染树。
- 根据渲染树完成绘制的过程。
而在真实页面解析过程中,浏览器通常会因为各种因素被阻断。
- HTML代码中的JavaScript代码(简称JS代码)会阻断DOM树的构造
- 因为浏览器认为这段JS代码可能会修改DOM结构,所以必须等待JS代码执行完毕,再恢复DOM树的构造过程。这是由浏览器的安全解析策略决定的
- 浏览器必须等待样式表加载完成,才能开始构建CSSOM树。
还有一种特殊情况,浏览器在解析HTML时遇到JS代码,而此时CSSOM树还未构建完成,则浏览器会暂停脚本的执行
- (浏览器同时也会暂停继续向下解析HTML代码,从而导致DOM树的构建过程被暂停阻塞),直到CSS样式文件下载完成,并完成CSSOM树的构建,才会重新恢复原来的解析。这也是由浏览器的安全解析策略决定的。
详细的标签对于dom解析的影响,可以参考博主的姊妹篇和和dom解析渲染之间的关系
通过对上面各因素的分析,我们可以发现,HTML中的内联JS代码执行的危害之处,不在于它阻断了 DOM 树的构建过程,除非是一段特别恶劣的 JS 代码运行非常慢。
- 通常内联的 JS代码运行大概消耗几十毫秒,也就是暂停构建几毫秒到几十毫秒。
- 它最大的危害在于上面第三种情况提到的,即DOM树构建被阻塞的时间不是只有JS代码运行的时间,而是会加上样式资源文件下载和CSSOM 树的构建时间,这时浏览器所进行的串行解析过程,与我们在前面期望的DOM树和CSSOM树的并行解析过程相差甚远。
过程图:
优化策略:
根据渲染步骤,大概可以从以下几个方面着手:
- 优化HTML代码和结构,缩短HTML下载时间,加快HTML解析速度。
- 优化CSS文件和结构,缩短CSS文件下载时间和解析时间。
- 合理优化Js代码。并合理放置JS代码,避免前面第三种情况的出现,这也是最重要的。
具体的优化可以参考 博主的姊妹篇:
部分参考丛书《大型网站性能优化实战:从前端、网络、CDN到后端、大促的全链路性能优化详解》