深入浏览器渲染原理

220 阅读5分钟

深入浏览器渲染原理

  1. 网页的解析过程
  2. 浏览器渲染流程
  3. 回流和重绘解析
  4. 合成和性能优化
  5. defer和async属性

1.网页的解析过程

  1. 浏览器输入一个域名
  2. 经过域名解析(DNS解析),得到服务器的IP地址。
  3. 通过IP地址请求相应的页面,随后返回页面代码(一般只返回html),浏览器进行解析。
    1. 如果遇到css资源,向服务器请求
    2. 如果遇到js文件,再次向服务器请求

1.2浏览器内核

常见的浏览器内核

  • Trident(三叉戟):IE、360安全浏览器、搜狗高速浏览器、百度浏览器、UC浏览器;
  • Gecko(壁虎):Mozilla Firefox;
  • Presto(急板乐曲)->Blink(眨眼):Opera
  • Webkit:Safari、360极速浏览器、搜狗高速浏览器、移动端浏览器(Android、iOS)
  • Webkit->Blink Google Chrome,Edge

浏览器内核也叫排版引擎、页面渲染引擎、样板引擎。

2.渲染页面的详细流程:

image.png

  1. 解析一:HTML解析过程
    • 默认情况下服务器会给浏览器返回.html文件,所以解析html是所有步骤的开始
    • 解析HTML会构件DOM tree。
  2. 解析二:CSS文件解析
    • 在解析过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件。
      • 注意:下载CSS文件是不会影响DOM解析的
    • 浏览器下载完CSS文件之后,就会对CSS文件进行解析,解析出对应的规则树
      • 我们称为CSSOM(CSS对象模型)
  3. 解析三:构建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中。
  4. 解析四:布局和绘制
    • 第四步在渲染树(Render Tree)上进行布局,并且计算每个节点的几何体。
      • 渲染树会表示哪些节点以及其他样式,但是不表示每个节点的尺寸位置等信息
      • 布局是确定呈现树中所有节点的宽度、高度和位置信息。
    • 第五步是将每个节点绘制在屏幕上
      • 在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点
      • 包括将元素的可见部分进行绘制,比如文本、颜色、边框等等。

3. 回流和重绘

3.1 理解回流reflow(重排)

  • 第一次确定节点的大小和位置,称之为布局(layout)
  • 之后对节点大小、位置修改重新计算就叫做回流

3.2 引起回流的情况

  • DOM结构发生变化(添加/删除节点)
  • 改变了布局(修改一些属性width height等等)
  • 窗口尺寸发生改变
  • 调用getComputedStyle方法获取尺寸、位置信息

3.3 理解重绘

  • 第一次渲染内容称为绘制
  • 之后重新渲染称之为重绘

3.4 引起重绘的情况

  • 修改背景颜色、文字颜色、边框颜色、样式等等。

注意:

回流一定会引起重绘,回流很消耗性能。

开发中要尽力避免发生回流

  1. 修改样式尽量一次性更改
  2. 尽量避免频繁操作DOM
  3. 尽量避免通过getComputedStyle获取尺寸、位置等信息
  4. 对某些元素使用position的absolute或者fixed。

4.特殊解析-composite合成

在绘制的过程中,可以将布局后的元素绘制到多个合成图层中。

  • 这是浏览器的一种优化手段

默认情况下,标准流的内容都是被绘制在同一个图层中的。

  • 一些特殊的属性,会创建一个新的图层,在这个新的图层里面对界面进行更改,只会在该图层进行回流或者重绘,这样对性能要求更低。

下面是一些会形成新图层的属性:

  1. 3D transforms
  2. video canvas iframe
  3. opacity 动画转换时
  4. position:fixed
  5. will-change
  6. 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之前或者之后执行。