浏览器渲染流程
ruhangs
·发布于 1 个月前·
0 人看过

一、渲染流程

bash

1、使用html解析器将html页面转成浏览器所认识的DOM树 ParseHTML 2、将css解析成浏览器能够识别的cssom 3、样式计算 4、DOM树+CSS数据结合成布局树 5、根据布局树生成图层树

下面我们将详细介绍浏览器的渲染流程。通常来说,浏览器渲染流程包括以下几个步骤:

image1.png

1. 解析 HTML

当浏览器向服务器获取 HTML 文档的请求时,服务器返回二进制流格式的 HTML 页面,响应头 Content-Type 值为 text/html,这里 text/html 是 MIME 类型,它告诉浏览器它是一个 HTML 文档。

image2.png

当浏览器收到 HTML 数据时,主线程开始解析文本字符串(HTML)并将其转换为文档对象模型(DOM),在浏览器开发者工具 console 中 输入 document 即可看到一个完整的 DOM 树结构。

image3.png

  • 当 HTML 解析器发现 <script>标签时,会暂停 HTML 文档的解析,并必须加载、解析和执行JavaScript代码,即<script>标签会阻塞 DOM 的解析和渲染。

image.png

  • <link>标签不会阻塞 DOM 的解析,但是会阻塞 DOM 的渲染,同时还会阻塞之后的 <script> 标签的执行。
  • <link rel="preload"> preload 属性 会预加载资源。
  • <link rel="dns-prefetch"> dns-prefetch 属性 (DNS 预获取) 是尝试在请求资源之前解析域名,仅对跨域域上的 DNS 查找有效。

2. 样式计算(Style)

主线程解析 CSS 并确定每个 DOM 节点的计算样式,目的是为了计算出 DOM 节点中每个元素的具体样式。经过计算,每个元素节点都会有一个最终样式,在浏览器开发者工具 Elements -> Computed 即可查看。

image.png

样式计算主要有以下三个步骤:

2.1 把 CSS 转换为 styleSheets

CSS 样式主要来源:

  • <link>标签
  • <style>标签
  • 元素的Style属性

浏览器无法直接理解纯文本的CSS样式,当渲染引擎接收到 CSS 文本时,会将 CSS 文本转换为浏览器可以理解的 styleSheets 结构。<br />在浏览器开发者工具 console 中 输入 document.styleSheets 即可看到所有解析后 CSS 样式。<br />如果不提供任何 CSS,也会有默认样式。 如 <h1> 标签显示大于 <h2> 标签,这是因为浏览器具有默认样式表。如果你想知道 Chrome 的默认 CSS 是什么样的,你可以在这里看到源代码

2.2 标准化样式表中的属性值

css

body { font-size: 2em } p { color: blue } span { display: none } div { font-weight: bold } div p { color: green } div { color: red }

可以看到上面的 CSS 文本中有很多属性值,如 2em、blue、bold,这些属性值不被渲染引擎理解,需要将所有值转换为渲染引擎容易理解的、标准化的计算值,这个过程就是属性值标准化。如 2em 被解析成 32px,red 被解析成了 rgb(255, 0, 0),bold 被解析为 700。

2.3 计算出每个 DOM 节点的具体样式

每个 DOM 节点的样式属性,是 CSS 继承规则和层叠规则 进行叠加计算的结果。层叠是 CSS 的一个基本特征,继承指的是某些样式属性会从父元素传递给子元素,而层叠则是指当多个样式规则应用到同一个元素时,浏览器根据一定的规则确定最终的样式值。

3. 布局(Layout)

现在,我们知道文档的结构和每个节点的样式,但这还不足以显示页面,因为我们还不知道 DOM 元素的几何位置信息。 布局阶段是浏览器确定每个元素在页面中的位置和大小的过程。在布局过程中,浏览器会根据元素的盒模型、样式属性等计算出每个元素的位置和尺寸。

image.png

Chrome 在布局阶段需要完成两个任务:创建布局树和布局计算。

3.1 创建布局树

遍历 DOM 树中的每一个节点,过滤不可见的元素(比如 head 标签,比如具有 display:none 样式的元素),将所有的可见元素构建一棵只包含可见元素布局树(具有 visibility: hidden 的元素会在布局树中)。

3.2 布局计算

有了布局树之后,就需要对布局树中各节点的几何坐标位置进行计算,其中包含 x,y 坐标和边界框大小等信息。

4. 分层(Layer)

主线程遍历布局树,根据策略对布局树进行分层,并生成一棵对应的图层树。Chrome 引入了分层和合成的机制就是为了提升每帧的渲染效率。

image.png

在浏览器开发者工具 (Layers) 可以查看可视化页面的分层情况,如下图所示:

image.png

什么样的节点会创建独立的图层?

  • position 属性值为 fixed 或者 sticky
  • opacity 属性值小于 1
  • z-index 属性值不为 auto
  • transform、filter、perspective、clip-path 属性值不为 none
  • 在 will-change 中指定了任意CSS属性

5. 绘制(Paint)

有了图层树后,主线程会为每个图层单独绘制指令集,用于描述这一层的内容该如何画出来。如把画笔移到某个位置,先画什么再画什么,把一个图层的绘制拆分成很多小的 绘制指令 ,然后再把这些指令按照顺序组成一个 待绘制列表。<br />主线程将每个图层的绘制信息提交给合成线程(compositor thread) ,剩余工作将由合成线程完成。

6. 分块(Tiling)

浏览器渲染分块用于将页面分割为多个独立的块,然后分别渲染这些块。每个块都是独立的渲染区域,并且可以单独更新和绘制,以提高渲染性能和响应速度。

  • 页面分割: 浏览器将页面划分为多个独立的块。通常,这些块的大小是固定的,例如 256x256 像素。每个块都有自己的位置和尺寸。
  • 多线程处理: 浏览器可以使用多个线程来并行处理分块。这使得浏览器能够更高效地利用硬件资源。

7. 光栅化(Raster)

光栅化是将页面上的图形、文本和其他可见元素转换为像素的过程。在浏览器中,页面的可视内容通常以矢量形式表示,但在显示器上呈现时需要将其转换为光栅图像(由像素组成的位图)。 合成线程将分块信息交给 GPU 进程,GPU 进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块,将生成位图

image.png

8. 画(Draw)

合成线程拿到每个图层、块的位图后,生产一个个 指引(quad) 信息,指引会标识出每个位图应该画在屏幕的哪个位置,以及会考虑旋转,缩放等变形。 transform 发生在合成线程,与渲染主线程无关,所以这就是 transform 效率高的本质原因。

二、优化

1. 重排(reflow)

reflow 的本质是重新计算 layout 树,以下的操作都会导致页面 reflow :

  • 页面首次渲染。
  • 浏览器窗口大小发生变化。
  • 元素的内容发生变化。
  • 元素的尺寸或者位置发生变化。
  • 元素的字体大小发生变化。
  • 激活 CSS 伪类。
  • 查询某些属性或者调用某些方法。
  • 添加或者删除可见的 DOM 元素。

为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当 JS 代码全部完成后再进行计算,所以改动属性造成的 reflow 是异常完成,也因此 当 JS 获取布局属性时,可能无法获取到最新的布局信息。 浏览器在反复权衡下,最终决定获取属性立即 reflow。 如调用 dom.clientWidth。

2. 重绘(repaint)

repaint 的本质就是重新根据分层信息计算绘制指令,以下的操作会导致 repaint:

  • 改变 color、background 相关属性:background-color、background-image。
  • 改变 outline 相关属性:outline-color、outline-width 、text-decoration。
  • 改变 border-radius、visibility、box-shadow。

当改动了可见样式后,就需要重新计算,会引发 repaint。<br />元素的布局信息也属于可见样式,所以 reflow 一定会引起 repaint。

3. 为什么 transform 效率高

因为 transform 既不会影响布局也不会影响绘制指令,它只会影响渲染流程的最后一步 draw 阶段,由于 draw 在合成线程中,所以 transform 的变化几乎不会影响到渲染主线程。但是必须结合图层做,will-change: transform

4. 其他优化的点

1、采用 opacity 代替 visibility,其机制和 transform 一致 2、将多次改变样式的操作合并成一次 3、利用文档碎片(documentFragment) 4、不要把获取某些 DOM 节点的属性值放在一个循环里面当成循环的变量

当获取文档的 width.height 的时候会触发重绘和重排

5、为动画元素新建图层

浏览器