浏览器页面渲染机制【2023】
# 0.前言
去年(2022) 年,已写了篇博客《浏览器页面渲染机制》 对浏览器的机制进行了梳理,发现对其中的一些概念还存在模糊的理解。故,本篇文章进一步从浏览器的渲染流程入手,分析页面渲染机制。
# 1. 简述浏览器的渲染流程
== 下载 css 文件 ==
↑ ↓
预解析线程: 解析到如 `link` 标签后 → 启用网络线程 → CSSOM
↑ |
(渲染主进程) | ↓
渲染主线程: `parse HTML` → `recaculate style` → `layout` → `composite` → `paint`
合成线程: → `Tiling` `Tiles` → `Raster` 位图 → `Draw`
↓ ↑ | ↑ |
(线程池)分块线程1、分块线程2、分块线程3 | | |
↓ | ↓
GPU 进程: == GPU 进程(光栅化)=== 矩阵运算
|
↓
(安全)调用 GPU 硬件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2. 细节解析
parse HTML其中涉及到
JS阻塞DOM解析线程,推荐使用defer字段。css的四种方案。<style><link ....><div style ="">内联浏览器默认样式表
document.styleSheets → StyleSheetList document.styleSheets[0].addRule('div','border:2px solid #f40 !important')1
2
扩展:现代浏览器的额外优化,使用预解析器,预先下载可点击链接的内容(预解析线程)
recaculate style- 此阶段将
DOM树 +CSSOM树 合并。 - 可通过
document.getComputedStyle或computed面板获取该计算的值。 - 此阶段的作用
- 相对单位
em→ 绝对单位px - 预设值
red→ 绝对值rgba(255,0,0,0)
- 相对单位
- 此阶段将
laylout计算(几何信息)C++对象。- 哪写属性会影响几何信息的计算?
width、heightfont-size- 计算 相对定位,其中相对的是包含块?
DOM树和Layout树的区别?- 会少:
Layout只会对DOM树的可见部分进行生成。- 如,此时会根据
CSS选择器,找到display: none
- 会多:
- 伪元素
:before或者:after - 新增 匿名行盒 和 匿名块盒,满足以下规则:
- 文本等内容必须在 匿名行盒 中。
- 行盒和块盒是不能相邻的,所以会新增 匿名快盒。
- 伪元素
- 会少:
- 是否可以使用通过
js访问Layout树?【重绘操作】- 不可以,因为该树为
C++对象,可通过document.body.clientWidth/offset读取内置暴露出的 布局信息 。 - 注意的点是:
js对dom操作行为的表现是不同的,设置是 异步操作,而读取行为属于 同步 操作,读取行为会立即触发 重绘 操作。- 设置:
dom.style.width = ?,这里异步的原因是可以多个设置行为合并为一次批处理行为,减少浏览器的渲染消耗。 - 读取:
document.body.clientWidth,立即触发重绘。
- 设置:
- 不可以,因为该树为
composite分层- 该行为由浏览器自动分配。
- 与分层属性有关:
- 如:
z-index属性。 - 其中
will-change会极大影响分层结果。
- 如:
paint绘制指令- 渲染主线程会为每个 图层 生成绘制指令集,用于描述这一层的内容该如何画出来。
- 完成绘制后,主线程结束,会将每个图层的绘制信息提交给合成线程,剩余工作将由 合成线程 完成。
Tiling分块- 将每一层分为多个小的区域,内部会触发分块线程,会从多个 线程池 中拿取多个线程来完成工作。
Raster光栅化(会调用 GPU 进程)计算出位图。- 作用:将 块 转 化为 位图。
- 采用
GPU可以加快光栅化的速度。 - 优先处理靠近视口位置的快,并将后续结果会交给
合成线程。
Draw生成 像素信息会生成
quad(指引信息)(此阶段会执行
transform等旋转或者缩放的变变形,即进行矩阵运算。)这里会有一个特点,需要先交给
GPU进程,再由GPU进程交给GPU硬件进行计算。原因:整个渲染进程是在 沙盒 中执行的,不会影响操作系统,不会进行系统调用。
# 3. 对应的面试题
- 解释
reflow原理。 - 解释
repaint原理。
# 参考文章
编辑 (opens new window)
上次更新: 2023/11/05, 21:11:00