[关闭]
@panhonhang 2018-12-08T13:32:09.000000Z 字数 2933 阅读 559

渲染性能

性能优化


一、浏览器渲染页面的过程。

此处输入图片的描述

    1.解析HTML生成DOM树。
    2.解析CSS生成CSSOM规则树。
    3.将DOM树与CSSOM规则树合并在一起生成渲染树。
    4.遍历渲染树开始布局,计算每个节点的位置大小信息。
    5.将渲染树每个节点绘制到屏幕。

1.构建DOM树

DOM树构建过程:

字节 -> 字符 -> 令牌 -> 节点对象 -> 对象模型

二、优化处理

  1. 使用RequestAnimationFrame函数实现动画

    • 在使用JavaScript实现动画效果的时候,时机不当的运行JavaScript或长时间运行的JavaScript都会导致导致性能下降。避免使用setTimeout()或者setInterval()函数来实现动画效果,这种做法的主要问题是回调将会在帧中的某个时间点运行,这可能会刚好在末尾(会丢失帧导致发生卡顿)。将 setTimeout 换成 requestAnimationFrame,因为 setTimeout 时间控制可能造成在一帧的中间,目前各浏览器对 requestAnimationFrame 的支持已经比较好了。

    • requestAnimationFrame概述:

      requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。
      设置这个API的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。代码中使用这个API,就是告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘。

    • requestAnimationFrame的优势

      在于充分利用显示器的刷新机制,比较节省系统资源。显示器有固定的刷新频率(60Hz或75Hz),也就是说,每秒最多只能重绘60次或75次,requestAnimationFrame的基本思想就是与这个刷新频率保持同步,利用这个刷新频率进行页面重绘。此外,使用这个API,一旦页面不处于浏览器的当前标签,就会自动停止刷新。这就节省了CPU、GPU和电力。
      不过有一点需要注意,requestAnimationFrame是在主线程上完成。这意味着,如果主线程非常繁忙,requestAnimationFrame的动画效果会大打折扣。
      requestAnimationFrame使用一个回调函数作为参数。这个回调函数会在浏览器重绘之前调用。

  2. 使用CSS的媒体查询来优化CSS。

    • 如果可以让CSS资源只在特定条件下使用,这样这些资源就可以在首次加载时先不进行构建CSSOM树,只有在符合特定条件时,才会让浏览器进行阻塞渲染然后构建CSSOM树。使用媒体查询可以让CSS资源不在首次加载中阻塞渲染,但不管是哪种CSS资源它们的下载请求都不会被忽略,浏览器仍然会先下载CSS文件。

    <!-- 没有使用媒体查询,这个css资源会阻塞渲染 -->
    <link href="style.css" rel="stylesheet">
    <!-- all是默认类型,它和不设置媒体查询的效果是一样的 -->
    <link href="style.css" rel="stylesheet" media="all">
    <!-- 动态媒体查询,将在网页加载时计算。根据网页加载时设备的方向,portrait.css 可能阻塞渲染,也可能不阻塞渲染。-->
    <link href="portrait.css" rel="stylesheet" media="orientation:portrait">
    <!-- 只在打印网页时应用,因此网页首次在浏览器中加载时,它不会阻塞渲染。 -->
    <link href="print.css" rel="stylesheet" media="print">

  3. 改变JavaScript的执行位置。

    • 当浏览器的HTML解析器遇到一个script标记时会暂停构建DOM,然后将控制权移交至JavaScript引擎,这时引擎会开始执行JavaScript脚本,直到执行结束后,浏览器才会从之前中断的地方恢复,然后继续构建DOM。每次去执行JavaScript脚本都会严重地阻塞DOM树的构建,如果JavaScript脚本还操作了CSSOM,而正好这个CSSOM还没有下载和构建,浏览器甚至会延迟脚本执行和构建DOM,直至完成其CSSOM的下载和构建。显而易见,如果对JavaScript的执行位置运用不当,这将会严重影响渲染的速度。

    对于必须要在DOM加载之前运行的JavaScript脚本,我们需要把这些脚本放置在页面的head中,而不是通过外部引用的方式,因为外部的引用增加了网络的请求次数;并且我们要确保内敛的这些JavaScript脚本是很小的,最好是压缩过的,并且执行的速度很快,不会造成浏览器渲染的阻塞。

    对于支持使用script标签的async和defer属性的浏览器,我们可以使用这两个属性;其中需要注意的点就是,async表示的意思是异步加载JavaScript文件,它的下载过程可以在HTML的解析过程中进行,加载完成之后立即执行这个文件的代码,执行文件代码的过程中会阻塞HTML的解析,它不保证文件加载的顺序。defer表示的意思是在HTML文档解析之后在执行加载完成的JavaScript文件,JavaScript文件的下载过程可以在HTML的解析过程中进行,它是按照script标签的先后顺序来加载文件的。

参考博文:
该把JS文件放在HTML文档的那个位置
浏览器渲染页面过程与页面优化
浏览器渲染过程与性能优化

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注