浏览器渲染原理-概述

678 阅读4分钟

渲染主流程

image.png

主流程分为五个阶段

  1. 解析阶段
  2. 构建渲染树阶段
  3. 布局阶段
  4. 绘制阶段
  5. 渲染阶段

解析阶段

分为两个独立部分:HTML解析、样式解析

HTML解析(HTML->DOM)

<!doctype HTML>
<html>
 <head>
  <meta charset="UTF-8"/>
  <title>My simple page</title>
  <link rel="stylesheet" src="styles.css"/>
  <script src="myscript.js"></script>
</head>
<body>
  <h1 class="heading">My Page</h1>
  <p>A paragraph with a <a href="https://example.com/about">link</a></p>
  <div>
    <img src="myimage.jpg" alt="image description"/>
  </div>
  <script src="anotherscript.js"></script>
</body>
</html>

image.png

HTML解析是顺序的,从第一行代码片开始,逐一解析。解析过程中遇到外联资源(image、iframe、link、script)会立即请求对应的资源。

这些资源简单分为阻塞性和非阻塞性两种:

  • 阻塞性:当前HTML解析停止,拉取对应资源并立即解析。完成之后再重新回到HTML解析
    • 内联javascript资源
    • 外联普通javascript资源
    • 外联defer javascript资源
    • 内联css资源
  • 非阻塞性:不影响当前HTML解析
    • image
    • iframe
    • 外联async javascript

样式解析(CSS->CSSOM)

构建CSSOM树与构建DOM树相似,其中CSSOM树与DOM树结构相似但并不相同。 如下图所示:CSS会根据用户CSS文件来解析出叠层样式,其解析单位是已选择器来的,可以是元素标签、class以及id,最终得到单位的样式描述值。例:.error class选择器,得到描述值color: red。 image.png

构建渲染树阶段(DOM+CSSOM->Render Tree)

Render树通过DOM和CSSOM相结合形成。

需要注意的是,DOM树结构和CSSOM树形结构并不相同,Render树和DOM树相同。在DOM和CSSOM相结合时,以DOM树根节点为基准,遍历CSSOM树并最终获得每一个dom节点的叠层样式。

需要注意,CSSOM中样式并不完全,它是内联样式+外联样式+用户自定义样式+浏览器默认样式共同构成。如用户在p标签设置了font-size值,但没有设置color,此时浏览器会逐一通过优先级来获取具体的值。 image.png

布局阶段(layout)

此过程能回得到第四个树:呈现树(包含渲染树的样式以及本步骤得到的集合数据)。 也叫重排。目的是获取每一个元素在浏览器视口的几何数据(位置、大小等)。由于浏览器默认为流式布局,排在前面或者上面已经定位的元素,所以布局是从上到下,从左到右依次解析。

布局同上遵守以下模式:

  1. 父呈现器确定自己的宽度
  2. 父呈现器依次处理子呈现器
  3. 放置子呈现器(设置x、y坐标)
  4. 父呈现器下所有子呈现器处理完毕之后,根据子呈现器的累加高度、边距和补白的高度来设置自身高度。(2、3、4是一个递归的过程,直到最末级)

布局分为两种模式:

  • 全局:重新布局整个渲染树,重新获取完整的呈现树。
  • 增量:不会重新布局,仅修改部分以及部分受影响部分重新布局。

绘制阶段(paint)

根据呈现树规则,遍历并调用呈现器的paint方法,将呈现器的内容显示的屏幕上。和布局相同,分为两个部分,全局会重新绘制整个屏幕显示;增量只需重新绘制修改部分。

块呈现器堆栈顺序:

  1. 背景颜色
  2. 背景图片
  3. 边框
  4. 子代元素
  5. 轮廓

渲染阶段(display)

把文档的结构、元素的样式、几何形状和绘制顺序转换为屏幕上的像素称为光栅化。合成是一种将页面的各个部分分层,分别栅格化,并在一个被称为合成器线程的独立线程中合成为页面的技术

一旦创建了层树并确定了绘制顺序,主线程就会将该信息提交给合成器线程。 合成器线程然后栅格化每个图层。 一个图层可能像页面的整个长度一样大,因此合成器线程会将它们分成图块,并将每个图块发送到光栅线程(Raster)。 栅格线程栅格化每一个瓦片(tile)并将它们存储在GPU内存中。

通过IPC将合成器帧提交给浏览器进程。这时可以从UI线程添加另一个合成器帧以用于浏览器UI更改,或者从其他渲染器进程添加扩充数据。 这些合成器帧被发送到GPU用来在屏幕上显示。 如果发生滚动事件,合成器线程会创建另一个合成器帧并发送到GPU。

合成的好处是它可以在不涉及主线程的情况下完成。 合成线程不需要等待样式计算或 JavaScript 执行。 这就是合成动画是平滑性能的最佳选择的原因。 如果需要再次计算布局或绘图,则必须涉及主线程。

参考:

渲染页面:浏览器的工作原理

webkit解析CSS过程详解

浏览器是如何工作的 下 布局与绘制

现代浏览器渲染过程