@panhonhang
2018-12-08T13:32:09.000000Z
字数 2933
阅读 559
性能优化
1.解析HTML生成DOM树。
2.解析CSS生成CSSOM规则树。
3.将DOM树与CSSOM规则树合并在一起生成渲染树。
4.遍历渲染树开始布局,计算每个节点的位置大小信息。
5.将渲染树每个节点绘制到屏幕。
1.构建DOM树
DOM树构建过程:
字节 -> 字符 -> 令牌 -> 节点对象 -> 对象模型
处理HTML标记
浏览器从磁盘或网络读取 HTML 的原始字节。 然后将HTML的原始字节数据按照相应编码规范转换为文件指定编码的字符。
令牌化
然后浏览器会根据HTML规范来将字符串转换成各种令牌。令牌记录了标签的开始与结束,通过这个特性可以轻松判断一个标签是否为子标签。
生成节点对象
每个令牌都会被转换成定义其属性和规则的节点对象。
DOM树构建完毕
DOM树构建完成,整个对象集合就像是一棵树形结构。DOM是一个树形结构,这是因为标签之间含有复杂的父子关系,树形结构正好可以诠释这个关系。
2.构建CSSOM树。
过程与构建DOM树类似。
字节 -> 字符 -> 令牌 -> 节点对象 -> 对象模型
3.构建渲染树
从 DOM 树的根节点开始,遍历每个可见的节点。
渲染树构建完成,每个节点都是可见节点并且都含有其内容和对应规则的样式。。
4.布局阶段
布局阶段就是遍历渲染树的根节点,确定每个节点对象在页面上的确切大小与位置,最后输出一个盒子模型,这个模型会精确地捕获每个元素在屏幕内的确切位置与大小,并且所有的相对的测量值都会被转换为屏幕内的绝对像素值。
5.绘制阶段
系统会遍历呈现树,并调用呈现器的“paint”方法。
绘制工作是使用用户界面基础组件完成的。CSS2 规范定义了绘制流程的顺序。绘制的顺序其实就是元素进入堆栈样式上下文的顺序。这些堆栈会从后往前绘制,因此这样的顺序会影响绘制。
块呈现器的堆栈顺序如下:
背景颜色、背景图片、边框、子代、轮廓
二、优化处理
使用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使用一个回调函数作为参数。这个回调函数会在浏览器重绘之前调用。
使用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">
改变JavaScript的执行位置。
对于必须要在DOM加载之前运行的JavaScript脚本,我们需要把这些脚本放置在页面的head中,而不是通过外部引用的方式,因为外部的引用增加了网络的请求次数;并且我们要确保内敛的这些JavaScript脚本是很小的,最好是压缩过的,并且执行的速度很快,不会造成浏览器渲染的阻塞。
对于支持使用script标签的async和defer属性的浏览器,我们可以使用这两个属性;其中需要注意的点就是,async表示的意思是异步加载JavaScript文件,它的下载过程可以在HTML的解析过程中进行,加载完成之后立即执行这个文件的代码,执行文件代码的过程中会阻塞HTML的解析,它不保证文件加载的顺序。defer表示的意思是在HTML文档解析之后在执行加载完成的JavaScript文件,JavaScript文件的下载过程可以在HTML的解析过程中进行,它是按照script标签的先后顺序来加载文件的。