浏览器页面渲染机制【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
、height
font-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