网页加载性能优化方法研究

网页的加载性能是影响用户体验的最重要因素,页面加载时间过长,极有可能会令用户直接关闭网页,即便网页自己的流程和UI等方面优化得再出色,也不会有任何价值。本文将以优化网页加载性能的角度出发,介绍网页渲染的过程以及各种资源阻塞网页渲染的状况,并给出优化的方向
(本文以Chrome为主浏览器进行讨论,其余浏览器可能会存在细微不一样的状况,不在本文讨论的范围)css

网页的渲染过程

五个步骤

想要知道如何优化网页加载性能,首先得清楚浏览器加载一个网页通过了哪些步骤,才能明白应该从哪些方面着手优化。通常来讲,浏览器从服务器端获取到HTML文件后就开始了加载过程,加载网页的过程包括以下五个步骤:html

  • HTML代码转化成DOM,并并行地获取外部资源(包括HTML中出现的JS、CSS、图片文件)
  • CSS文件下载完成,CSS代码转化成CSSOM(CSS Object Model)
  • 结合DOM和CSSOM,生成一棵渲染树(包含每一个节点的视觉信息)
  • 生成布局(Layout):将全部渲染树的全部节点进行平面合成,该步骤能够计算出元素在网页中的位置
  • 绘制(Paint):将网页内容绘制在屏幕上

在加载过程当中,前三步的耗时主要在于外部资源获取上,只有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解析到引用行再发请求的;
  • CSS文件加载的速度是影响首次Paint时间的因素,当CSS文件下载完成后才能进行CSSOM和渲染树的构建,而后才是Layout和Paint过程;
  • JS文件加载的速度不影响首次Paint时间,即便JS文件自己有修改DOM节点的操做,也只是在JS文件加载完成后再进行一次Layout和Paint;

各种资源阻塞网页加载的状况

阻塞网页加载的状况,能够分为两种:一种是阻塞HTML解析,即阻塞Event Log中的parse HTML步骤,令HTML结构中止解析;另外一种是阻塞渲染,即阻塞Event Log中的Paint步骤,令已经解析好的HTML结构也没法显示到浏览器上。

CSS资源

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资源

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时间的优化,咱们能够从如下角度进行考虑:

  • CSS会影响首次Paint的时间,应该尽快加载,所以将其放在head标签处以保障能在解析完HTML后发出请求;
  • JS不会影响首屏的时间,但因为JS会阻塞以后的页面内容的解析与渲染,要避免JS在首屏位置出现,通常将它们放在body的最后,另外,JS会影响总体页面加载的性能,可使用defer和async转成非阻塞模式(见参考文献[6]);
  • 图片不影响首屏时间,但会影响Load事件的时机(没有找到合适的参考文献,待我另起一篇文章补充);

参考文献

  1. 《js必定要放在底部吗?》https://segmentfault.com/a/11...
  2. 《聊聊浏览器的渲染机制》https://www.jianshu.com/p/c90...
  3. 《网页性能管理详解》http://www.ruanyifeng.com/blo...
  4. 《浏览器渲染过程与性能优化》https://sylvanassun.github.io...
  5. 《How browsers work》http://taligarsiel.com/Projec...
  6. 《JavaScript阻塞剖析与改善》http://www.cnblogs.com/giggle...
相关文章
相关标签/搜索