Web前端性能优化(一)

Web前端性能优化算是面试中很经典的问题了。Web前端性能优化是一个复杂的过程,涉及到的知识点非常多,包括网页,服务器,CSS,Javascript,图片等方面。

1. JS相关

  1. js的时间线;
    首先大家需要先了解js的时间线,在看完js的时间线之后我们就知道了为什么js要放到最下面加载,下面我就给大家看看js的时间线图:
    js的时间线
  2. 懒执行;
    所谓的懒执行就是将某些逻辑延迟到使用时再计算。该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏使用的,就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。
  3. 对DOM动画使用CSS类,而不是使用js;
  4. 使用快速DOM遍历,即document.getElementById();
  5. 指针引用存储到浏览器内对象中;
  6. 批量更改DOM,尤其是在更新样式时;
  7. 在将DOM添加到页面之前单独构建DOM;
  8. 在可滚动的DIV中使用缓冲的DOM。

2. 渲染相关

  1. 渲染过程优化
    想要对渲染过程优化理解好,就需要首先了解一下渲染机制:
    a. 处理HTML并构建DOM树;
    b. 处理CSS并构建CSSOM树;
    c. 将DOM与CSSOM合并成一个渲染树;
    d. 根据渲染树来布局,计算每个节点的位置;
    e. 调用GPU(即图形处理器,又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上做图像和图形相关运算工作的微处理器。)绘制,合成图层,显示在屏幕上。

注意:在构建CSSOM树时,会阻塞渲染,直至CSSOM树构建完成。并且构建CSSOM树时一个十分消耗性能的过程,所有应该尽量保证层级扁平,减少过度层叠,越是具体的CSS选择器,执行速度越慢。

  1. 重排(重排又被称为回流)重绘
    a. 重排重绘的整体概念:
    DOM的变化影响到了元素的几何属性(宽高),浏览器重新计算元素的几何属性,其他元素的几何属性和位置也会受到影响,浏览器需要重新构造渲染树,这个过程称为重排,浏览器将受到影响的部分重新绘制到屏幕上的过程称为重绘
    b. 重绘(repaint):和回流是渲染步骤中的一小节,但是这两个步骤对于性能影响很大。重绘是当节点需要更改外观而不会影响布局的,比如改变颜色color就称为重绘;
    c. 回流(reflow):是布局或者几何属性需要改变就称为回流;

注意:1. 重排一定重绘,重绘不一定重排。举一个例子:比如只对DOM元素操作其背景色,那么就只会发生重绘,不涉及几何元素会不会发生重排。2. 回流所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列回流。
d. 下列情况会发生重排:
1)首先是无法避免的,浏览器页面初始化渲染;
2)添加、删除可见DOM元素;
3)改变元素位置position;
4)改变元素尺寸(宽、高、内外边距、边框等);
5)改变元素内容(文本或图片等);
6)改变浏览器窗口尺寸。
注意:不同的条件下发生重排的范围及程度会不同,某些情况甚至会重排整个页面,比如:resize(window.resize事件会在窗口尺寸改变时触发,哪怕只是改变了1像素。)或者scroll。
e. 减少重排和重绘:
1)使用translate来替代top;
2)使用visibility来替换display:none,因为前者只会引起重绘,而后者会引发回流,因为改变了布局;
3)把DOM离线后修改,比如:先把DOM给display:none(此时有一次reflow回流),然后你修改100次,然后再把它显示出来;
4)不要把DOM节点的属性放在一个循环中,然后当成循环中的变量;
5)不要使用table布局,可能很小的一个小改动会造成整个table的重新布局;
6)动画实现速度的选择,动画速度越快,回流次数越多,我们也可以使用requestAnimationFrame;
7)CSS选择符从右往左匹配查找,避免DOM深度过深;
8)不在布局信息改变时做DOM查询,否则会导致渲染队列强制刷新;
9)使用cssText(本质就是设置HTML元素的style属性值)或者className一次性改变属性;
10)使用文档碎片fragment,如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排;
11)对于多次重排的元素,如动画,使用绝对定位(position:absolute|fixed)脱离文档流,让他的改变不影响到其他元素。

  1. 图层
    一般来说,可以把普通文档流看成一个图层。特定的属性可以生成一个新的图层。不同的图层渲染互不影响,所以对于某些频繁需要渲染的,建议单独生成一个新图层,提高性能。但也不能生成过多的图层,会引起反作用。

注意:将频繁运动的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于video标签,浏览器会自动将该节点变为图层。
通过以下几个常用属性可以生成新图层:
1)3D变换:translate3d、translateZ;
2)will-change通过告知浏览器该元素会有哪些变化,使浏览器提前做好优化准备,增强页面渲染性能;
3)video、iframe标签;
4)通过动画实现的opacity动画转换;
5)position:fixed。

  1. 懒加载
    懒加载就是将不关键的资源延后加载。懒加载的原理就是只加载自定义区域(通常是可视区域,但也可以是即将进入可视区域)内需要加载的东西。
    对于图片来说,先设置图片标签的src属性为一张占位图,将真实的图片资源放入一个自定义属性中,当进入自定义区域时,就将自定义属性替换为src属性,这样图片就会去下载资源,实现了图片懒加载。(懒加载不仅可以用于图片,也可以使用在别的资源上,比如进入可视区域才开始播放视频等等。)
    下面这张图是我再掘金网上看到的很详细的一个解释图片懒加载的原理:
    图片懒加载原理
    在这里我再提及上面图上的一点:就是为什么要尽量避免src里面为空?因为:避免使用空的 src 属性可以缩减浏览器首屏渲染的时间,因为浏览器在渲染过程中会把 src 属性中的空内容进行加载,直至加载失败,影响 DOMContentLoaded 与 Loaded 事件之间的资源准备过程,拉长了首屏渲染所用的时间。