浏览器的渲染过程可以用critical rendering path
来描述。
其包含以下几个步骤:
DOM
(文档对象模型)的构建DOM
是以我们熟悉的HTML
的元素节点构成的树状数据结构,可以通过devtools
的element
(元素)面板进行查看。
HTML
的解析并非是等整个文档下载下来后再进行的,而是从上至下的,并以一个个节点为单位逐步构建DOM
。
当遇到需要下载的外部资源如script
, link
, img
标签,则会将下载任务放到后台进行。这些外部资源当中,只有script
会阻塞HTML
的解析(内嵌的script
也会阻塞解析的执行)。
有时候我们并不希望下载script
的时候停止HTML
解析。于是HTML5
为script
标签增加了async
(下载完后自动执行),defer
(下载并HTML
解析完成后,根据在各defer
script
在文档中的位置(从上至下)按顺序执行)两个属性标志HTML
解析不需等待当前script
执行。
虽然下载外部CSS
不会阻塞HTML
的解析但会阻塞页面的渲染,具体的表现是它会阻塞在文档中处于它下面的节点的渲染。CSS
是render blocking
,script
是parser blocking
,这两种阻塞的不同点的其中一个表现是,在下载css
文件的时候,假如它下面还有其他需要下载资源(为什么知道还有其他资源需要下载,因为HTML
的解析没有被阻塞),这些资源也会并行下载。
DOMContentLoaded
事件是对应于HTML
解析完成的,而window.load
事件则是HTML
(初始的)外部资源都已下载完成时触发。
CSSOM
(CSS对象模型)的构建
当DOM
构建完以后,浏览器会读取所有来源(外部,内嵌,内联,浏览器默认)的CSS
来构建CSSOM
,CSSOM
是类似于DOM
的树状结构,不同的是它的节点带有CSS
信息,同时它会把非UI元素(如link
,title
,script
等)剔除。另外,CSS
的层叠式描述来源于样式可以继承的特性。- 渲染树的构建
渲染树是DOM
和CSSOM
的组合结果,它会将不可见元素(display:none
,换句话说不占任何空间的)剔除。 布局
布局过程会计算渲染树中各节点的大小和位置,这个过程另一个熟悉的名字reflow
(回流),触发reflow
的事件有:- 增删和更新元素
- 改变文字内容
- 移动元素
- 元素播放动画
- 获取元素的位置尺寸等属性或样式,如
offsetHeight
和getComputedStyle
- 改变CSS样式
- 改变元素类名
- 增删样式表
- 改变窗口大小
- 滚动
- 改变字体
- 激活伪元素
可以看出到reflow
是很容易就会触发的。
- 绘制
进行各元素的绘制,同时浏览器会为某些会频繁更新外观,有动画效果的(绘图层的创建理由的列举)元素额外创建一个绘图层,绘图层也有保证元素重叠时正确的绘制顺序的作用。使用devtools
的layer
(层)或rendering
(绘制)面板可看到层相关的信息。不同的绘图层的绘制过程是互不影响的。注意这一步还未将像素绘制到屏幕上。
合成
- 主线程将绘图层和绘制顺序的信息传到合成线程
- 各个绘图层会被传递到光栅线程中使用GPU进行光栅化(绘图层可能会很大,所以合成线程会将绘图层划分成一些小块发送到光栅线程),结果会储存到GPU内存中
- 合成线程会根据是否可能会展示到屏幕上来确定小块的光栅顺序
光栅完成后,合成线程将要绘制的小块生成合成帧,绘制到屏幕上
由于合成过程不在主线程进行,所以改变
transform
和opacity
这两个只作用于合成过程的属性的动画会比较流畅。从运算量来说影响layout
的css
属性 >paint
>composite
。下面是
css
属性及其影响环节的参考表格:
CSS properties by style operation required
本文主要引用自:
How the browser renders a web page? — DOM, CSSOM, and Rendering