网页的加载性能是影响用户体验的最重要因素,页面加载时间过长,极有可能会令用户直接关闭网页,即便网页自己的流程和UI等方面优化得再出色,也不会有任何价值。本文将以优化网页加载性能的角度出发,介绍网页渲染的过程以及各种资源阻塞网页渲染的状况,并给出优化的方向。
(本文以Chrome为主浏览器进行讨论,其余浏览器可能会存在细微不一样的状况,不在本文讨论的范围)css
想要知道如何优化网页加载性能,首先得清楚浏览器加载一个网页通过了哪些步骤,才能明白应该从哪些方面着手优化。通常来讲,浏览器从服务器端获取到HTML文件后就开始了加载过程,加载网页的过程包括以下五个步骤:html
在加载过程当中,前三步的耗时主要在于外部资源获取上,只有CSS资源下载完成才能完成第二第三步,生成渲染树;然后两步Layout和Paint较为耗时,且在网页渲染过程当中会执行屡次,其中首次Paint的耗时能够视为页面从空白到有内容的时间,减少这部分用时能够给用户以网页加载快的错觉。node
浏览器具有一些工具能够记录页面渲染的过程,进而帮助咱们分析哪些方面的性能还有提高的空间。
以最简单的HTML结构来熟悉一下Chrome中的Performance工具(以前的名字是timeline)。git
首先咱们打开控制台,切换到Performance工具,在页面加载前点击左上角的圆点,开始录制,页面加载完再次点击,中止录制,等数据分析完成切换到“Event Log”就能够开始查看渲染过程了。github
咱们先以最简单的结构进行分析,如加载下方index.html文件:web
<html lang="en"> <head> <meta charset="UTF-8"> <title>测试浏览器渲染</title> <link rel="stylesheet" href="./assets/style.css"> </head> <body> <h1>koa by html file</h1> <script src="./assets/script.js"></script> <img width="300" src="./assets/image.png"> </body> </html>
分析这个网页加载状况,以下截图所示:segmentfault
(上图为渲染五个步骤中的第一步,接收html文件解析并并行请求外部资源)浏览器
(上图为2, 3和4, 5步,接收到CSS文件后构建渲染树,进行Layout和首次的Paint)性能优化
(上图为Load事件以后的Paint)服务器
接着咱们修改一下node层代码,令CSS文件返回延迟5s,会获得以下“Event Log”
(css文件延迟5s后,会发现首次Layout和Paint都延迟到5s以后)
为了研究JS文件对首次Paint的影响,咱们令JS文件返回延迟5s,CSS和图片都即时返回,会获得以下“Event Log”
从上面的分析能够看出:
阻塞网页加载的状况,能够分为两种:一种是阻塞HTML解析,即阻塞Event Log中的parse HTML步骤,令HTML结构中止解析;另外一种是阻塞渲染,即阻塞Event Log中的Paint步骤,令已经解析好的HTML结构也没法显示到浏览器上。
CSS样式没法影响DOM结构,但能改变页面中元素呈现的模样,因此CSS资源能够阻塞渲染,但不会阻塞HTML解析。
为了研究CSS是否会阻塞渲染和解析,咱们依然使用以前的index.html文件,只将style.css延迟5s返回,获得以下实验结果:
(解析完HTML以后,就并行发JS、CSS和图片请求,JS和图片先接收完成,但没有触发首次Paint渲染,而是延迟到css文件接收完成,CSSOM和渲染树构建完成才触发了首次Paint,所以CSS资源会阻塞渲染)
相同状况下,页面的展现和HTML结构如何呢?请看下方动图:
(在CSS文件接收完成以前,虽然HTML结构已经解析完成,即Elements中HTML结构已经被解析出来,但页面是一片空白,说明CSS资源不会阻塞解析,但会阻塞渲染)
JS脚本会影响DOM结构,也能改变页面中元素呈现的模样,因此JS资源既能阻塞渲染又能阻塞HTML解析。
为了研究JS是否会阻塞渲染和解析,咱们依然使用index.html文件,只将script.js延迟5s返回,获得以下实验结果:
(并行发送请求,CSS和图片资源先加载完,触发了首次Paint渲染,此时JS文件还没开始下载,因此JS文件并不会影响页面的首次渲染)
(延迟了5s后,开始接收JS文件,完成后,再次Paint渲染)
相同状况下,页面的展现和HTML结构,请看下方动图:
(JS开始下载以前,CSS资源已经下载完成,页面也解析并渲染出一部份内容,这部分是JS文件由script标签引入以前的内容,而script标签以后的图片则需等到JS文件加载完成后才进行解析并渲染出来,所以JS资源会阻塞以后的HTML结构解析和渲染)
图片资源没法对其余DOM节点进行操做,因此不会阻塞渲染和HTML解析。
为了研究图片资源是否会阻塞渲染和解析,咱们依然使用index.html文件,只将png文件延迟5s返回,获得以下实验结果:
(并行发送请求,CSS和JS文件都加载后,完成HTML解析和首次Paint渲染)
(当图片文件加载完成后,再次渲染)
相同状况下,页面的展现和HTML结构,请看下方动图:
(图片加载以前,页面的HTML结构已经解析完成,而且画面也出如今屏幕上,说明图片资源不会阻塞HTML的解析和画面渲染)
从上面的实验能够看出,三种资源中只有CSS文件会影响首次Paint的时间。不管是延迟JS仍是图片,在CSS文件加载完成后,都能先渲染出已经解析好的HTML内容。因为在首次Paint以前,页面是一片空白,因此首次Paint的时间也就至关于首屏时间。
针对首次Paint时间的优化,咱们能够从如下角度进行考虑: