深入浏览器渲染原理
- 网页的解析过程
- 浏览器渲染流程
- 回流和重绘解析
- 合成和性能优化
- defer和async属性
1.网页的解析过程
- 浏览器输入一个域名
- 经过域名解析(DNS解析),得到服务器的IP地址。
- 通过IP地址请求相应的页面,随后返回页面代码(一般只返回html),浏览器进行解析。
- 如果遇到css资源,向服务器请求
- 如果遇到js文件,再次向服务器请求
1.2浏览器内核
常见的浏览器内核
- Trident(三叉戟):IE、360安全浏览器、搜狗高速浏览器、百度浏览器、UC浏览器;
- Gecko(壁虎):Mozilla Firefox;
- Presto(急板乐曲)->Blink(眨眼):Opera
- Webkit:Safari、360极速浏览器、搜狗高速浏览器、移动端浏览器(Android、iOS)
- Webkit->Blink Google Chrome,Edge
浏览器内核也叫排版引擎、页面渲染引擎、样板引擎。
2.渲染页面的详细流程:
- 解析一:HTML解析过程
- 默认情况下服务器会给浏览器返回.html文件,所以解析html是所有步骤的开始
- 解析HTML会构件DOM tree。
- 解析二:CSS文件解析
- 在解析过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件。
- 注意:下载CSS文件是不会影响DOM解析的
- 浏览器下载完CSS文件之后,就会对CSS文件进行解析,解析出对应的规则树
- 我们称为CSSOM(CSS对象模型)
- 在解析过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件。
- 解析三:构建Render Tree
- 根据DOM Tree与CSSOM Tree结合,就可以生成Render Tree。
- 注意:
- (1)link元素不会阻塞DOM Tree的构建过程,但是会阻塞RenderTree的构建过程,这是因为在Render Tree的构建过程中,需要CSSOM Tree。
- Render Tree和DOM Tree不是一一对应的关系,比如display值为none的元素,不会出现在Render Tree中。
- 解析四:布局和绘制
- 第四步在渲染树(Render Tree)上进行布局,并且计算每个节点的几何体。
- 渲染树会表示哪些节点以及其他样式,但是不表示每个节点的尺寸位置等信息
- 布局是确定呈现树中所有节点的宽度、高度和位置信息。
- 第五步是将每个节点绘制在屏幕上
- 在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点
- 包括将元素的可见部分进行绘制,比如文本、颜色、边框等等。
- 第四步在渲染树(Render Tree)上进行布局,并且计算每个节点的几何体。
3. 回流和重绘
3.1 理解回流reflow(重排)
- 第一次确定节点的大小和位置,称之为布局(layout)
- 之后对节点大小、位置修改重新计算就叫做回流
3.2 引起回流的情况
- DOM结构发生变化(添加/删除节点)
- 改变了布局(修改一些属性width height等等)
- 窗口尺寸发生改变
- 调用getComputedStyle方法获取尺寸、位置信息
3.3 理解重绘
- 第一次渲染内容称为绘制
- 之后重新渲染称之为重绘
3.4 引起重绘的情况
- 修改背景颜色、文字颜色、边框颜色、样式等等。
注意:
回流一定会引起重绘,回流很消耗性能。
开发中要尽力避免发生回流
- 修改样式尽量一次性更改
- 尽量避免频繁操作DOM
- 尽量避免通过getComputedStyle获取尺寸、位置等信息
- 对某些元素使用position的absolute或者fixed。
4.特殊解析-composite合成
在绘制的过程中,可以将布局后的元素绘制到多个合成图层中。
- 这是浏览器的一种优化手段
默认情况下,标准流的内容都是被绘制在同一个图层中的。
- 一些特殊的属性,会创建一个新的图层,在这个新的图层里面对界面进行更改,只会在该图层进行回流或者重绘,这样对性能要求更低。
下面是一些会形成新图层的属性:
- 3D transforms
- video canvas iframe
- opacity 动画转换时
- position:fixed
- will-change
- animation或者transition设置了opacity transform
虽然这样确实可以优化性能,但是它以内存管理为代价,所以不能过度使用。
5. script元素与页面解析的关系
在HTML解析的过程中,如果遇到script元素时,会等script元素下载解析完毕之后,才会继续执行,才会构建DOM树。
原因
因为JavaScript作用之一是操作DOM,如果等到DOM渲染完成之后再执行JavaScript,可能又会对DOM进行一些更改,造成回流,影响性能。所以遇到script元素时,会先执行script元素,在继续构建DOM。
6.defer与async使用
- defer:不会阻塞DOM tree的构建,告诉浏览器不用等待脚本下载,继续解析HTML。
如果代多个defer,他们是会按照顺序执行的。
- async:同样也可以不阻塞页面。
浏览器不会因为async脚本阻塞,async脚本不能保证顺序,但是它独立下载、独立运行,不会等待其他脚本。并且async不能保证脚本在DOMContentLoaded之前或者之后执行。