【JavaScript高级】浏览器原理:渲染引擎解析页面步骤、回流和重绘、composite合成、defer与async

文章目录

    • 渲染引擎解析页面的步骤
      • 解析1:HTML解析过程
      • 解析2:生成CSS规则
      • 解析3:构建Render Tree(渲染树)
      • 解析4:布局layout和绘制Paint
    • 回流和重绘
    • 特殊解析:composite合成
    • script元素和页面解析的关系
      • defer
      • async
      • defer与async
    • 参考

渲染引擎解析页面的步骤

我们常说的浏览器内核指的是浏览器的排版引擎,也称为浏览器引擎、页面渲染引擎,或样板引擎。一个网页下载下来后,就是由渲染引擎来帮助我们解析的。

解析过程如下:
【JavaScript高级】浏览器原理:渲染引擎解析页面步骤、回流和重绘、composite合成、defer与async_第1张图片

解析1:HTML解析过程

默认情况下服务器会给浏览器返回index.html文件,所以解析HTML是所有步骤的开始。

解析HTML会构建DOM Tree:
【JavaScript高级】浏览器原理:渲染引擎解析页面步骤、回流和重绘、composite合成、defer与async_第2张图片

解析2:生成CSS规则

  • 在解析的过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件
  • 注意:下载CSS文件是不会影响DOM的解析的
  • 浏览器下载完CSS文件后,就会对CSS文件进行解析,解析出对应的规则树
  • 我们可以称之为 CSSOM(CSS Object Model,CSS对象模型)

【JavaScript高级】浏览器原理:渲染引擎解析页面步骤、回流和重绘、composite合成、defer与async_第3张图片

解析3:构建Render Tree(渲染树)

有了DOM Tree和CSSOM Tree后,就可以两个结合来构建Render Tree了。
【JavaScript高级】浏览器原理:渲染引擎解析页面步骤、回流和重绘、composite合成、defer与async_第4张图片

注意:

  • link元素不会阻塞DOM Tree的构建过程,但是会阻塞Render Tree的构建过程:可以理解为link元素对应css的下载,DOM Tree的构建不需要css,但Render Tree需要
  • Render Tree和DOM Tree并不是一一对应的关系:如display为none的元素,不需要被渲染

解析4:布局layout和绘制Paint

布局layout:

  • 渲染树会表示要显示的节点及其样式,但不表示节点的尺寸、位置等信息,这些信息由布局呈现

绘制Paint:

  • 浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点

回流和重绘

回流

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

如何引起回流:

  1. DOM结构发生改变:添加或者移除节点
  2. 改变了布局
  3. 窗口resize
  4. 调用getComputedStyle方法获取尺寸、位置信息(有的浏览器在这里不会回流)

举个例子,有个box盒子很小,点了按钮后会变大,这样整个布局就会变化——这就是回流。

重绘

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

如何引起重绘:修改背景色、文字颜色、边框颜色、样式等。

注意

  • 回流一定会引起重绘,所以回流是一件很消耗性能的事情
  • 开发中要尽量避免发生回流,方法如下:
  • 修改样式时尽量一次性修改:如通过cssText修改,通过添加class修改
  • 避免频繁的操作DOM:可以在一个DocumentFragment或者父元素中将要操作的DOM操作完成,再一次性的操作
  • 避免通过getComputedStyle获取尺寸、位置等信息
  • 某些元素使用position的absolute或者fixed:会引起回流,而是开销较小,不会对其他元素造成影响(因为脱标了)

特殊解析:composite合成

绘制的过程,可以将布局后的元素绘制到多个图层中。这是浏览器的一种优化手段。

默认情况下,标准流中的内容都是被绘制在同一个图层(Layer)中的;
而一些特殊的属性,会创建一个新的合成层(CompositingLayer),并且新的图层可以利用GPU来加速绘制。因为每个合成层的都是单独渲染的。

可以形成新的合成层的常见属性(了解):

  • 3D transform
  • video、canvas、iframe
  • opacity 动画转换时
  • position:fixed
  • will-change:一个实验性的属性,提前告诉浏览器元素可能发生哪些变化
  • animation或者transition 设置了opacity、transform

分层确实可以提高性能,但是它以内存管理为代价,因此不应作为web优化性能优势策略的一部分过度使用。

script元素和页面解析的关系

  • 浏览器在解析HTML时,遇到script元素是不能继续构建DOM树的;
  • 它会停止继续构建,先下载JavaScript代码,并执行JavaScript的脚本,等到JavaScript脚本执行结束后,才会继续解析HTML,构建DOM树

原因:

  • JavaScript的作用之一是操作并修改DOM,若等到DOM树构建完成并且渲染再执行JavaScript,会造成严重的回流和重绘,影响页面的性能

这会带来新的问题:

  • 如今开发模式中(比如Vue、React),脚本往往比HTML页面更“重”,处理时间需要更长
  • 会造成页面的解析阻塞,在脚本下载、执行完成之前,用户在界面上什么都看不到;

因此,我们为了解决这个问题,script元素给我们提供了两个属性(attribute):deferasync

defer

作用:告诉浏览器不要等待脚本下载,而继续解析HTML,构建DOM Tree。

  • 脚本由浏览器下载,不会阻塞DOM Tree的构建过程
  • 如果脚本提前下载了,它会等待DOM Tree构建完成,在DOMContentLoaded事件之前先执行defer中的代码
  • 即:DOM Tree构建完成——执行defer中的代码——发生DOMContentLoaded事件
  • 多个带defer的脚本保持正确的顺序执行的(先执行第一个defer,执行第二个defer)
  • 从某种角度来说,defer可以提高页面的性能,推荐放到head元素中(提前让浏览器去下载)
  • defer 仅适用于外部脚本 ,对于script默认内容会被忽略

即,不要这样加:


<srcipt defer>
....
srcipt>

async

async是让一个脚本完全独立的:

  • 浏览器不会因 async 脚本而阻塞(与 defer 类似)
  • async脚本不能保证顺序,它是独立下载、独立运行,不会等待其他脚本
  • async不能保证在DOMContentLoaded之前或者之后执行

defer与async

  • defer通常用于需要在文档解析后操作DOM的JavaScript代码,并且对多个script文件有顺序要求的
  • async通常用于独立的脚本,对其他脚本,甚至DOM没有依赖的

参考

coderwhy的课
浏览器页面渲染过程
浏览器渲染原理
JavaScript高级 | 浏览器渲染过程

你可能感兴趣的:(JavaScript,javascript,前端,html)