blog6 min read
浏览器渲染流程学习笔记(Chromium)
浏览器渲染流程学习笔记(Chromium)
浏览器渲染流程学习笔记(Chromium)
一、渲染进程有哪些线程
1. 主线程(Main Thread)
负责:
- HTML 解析
- CSS 解析
- Style(样式计算)
- Layout(布局)
- Paint(绘制)
- Layerization(图层构建)
- JavaScript 执行
- 事件处理
Main Thread
├─ HTML Parse
├─ CSS Parse
├─ Style
├─ Layout
├─ Paint
├─ Layerization
└─ JavaScript
2. 合成线程(Compositor Thread)
负责:
- 管理 Layer Tree
- 页面滚动
- transform 动画
- opacity 动画
- 组织 Compositor Frame
Compositor Thread
├─ Scroll
├─ Animation
├─ Composite
└─ Frame Submission
3. 光栅化线程(Raster Threads)
负责:
Paint Commands
↓
Bitmap / Texture
将绘制指令转换成像素数据。
通常多个线程并行工作:
Raster Worker1
Raster Worker2
Raster Worker3
Raster Worker4
4. Worker线程
Web Worker
new Worker()
特点:
- 独立线程
- 不能操作DOM
Service Worker
负责:
- 离线缓存
- 消息推送
- PWA
5. V8后台线程
负责:
- GC垃圾回收
- JIT编译
- 优化编译
二、浏览器完整渲染流程
HTML
↓
DOM
CSS
↓
CSSOM
DOM + CSSOM
↓
Style
Style
↓
Layout
Layout
↓
Paint
Paint
↓
Layerization
Layer
↓
Raster
Bitmap / Texture
↓
Composite
Frame
↓
GPU
Screen
三、各阶段职责
1. HTML解析
输入:
<div>Hello</div>
输出:
DOM Tree
例如:
Document
└─ div
└─ Hello
作用:
描述页面有什么元素
2. CSS解析
输入:
div {
color:red;
}
输出:
CSSOM Tree
作用:
描述样式规则
3. Style(样式计算)
结合:
DOM Tree
+
CSSOM Tree
得到:
Computed Style
例如:
width:100px
height:50px
color:red
4. Layout(布局)
计算:
位置
大小
例如:
x=0
y=0
width=100
height=50
作用:
确定元素放在哪里
5. Paint(绘制)
生成绘制命令:
DrawRect(...)
DrawText(...)
DrawImage(...)
注意:
还没有像素
只是:
绘画说明书
6. Layerization(分层)
根据元素特征决定是否独立成层。
例如:
transform
opacity
position:fixed
video
canvas
will-change
形成:
Layer Tree
Root Layer
├─ Header Layer
├─ Content Layer
└─ Modal Layer
7. Raster(光栅化)
将:
DrawRect(...)
DrawText(...)
转换成:
RGBA
RGBA
RGBA
生成:
Bitmap
或者:
Texture
作用:
真正生成像素
8. Composite(合成)
管理:
Layer1
Layer2
Layer3
计算:
位置
透明度
变换
裁剪
层级
生成:
Compositor Frame
9. GPU
GPU负责:
纹理变换
透明度混合
图层叠加
裁剪
生成:
Final Frame
最终输出:
Screen
四、Paint、Raster、Composite区别
Paint
负责:
决定画什么
生成:
DrawRect(...)
DrawText(...)
Raster
负责:
真正画出来
生成:
Bitmap
Texture
Composite
负责:
把多个图层组合起来
生成:
最终一帧画面
五、JS在渲染过程中的处理
遇到script
<div>1</div>
<script>
</script>
<div>2</div>
流程:
HTML解析
↓
遇到script
↓
暂停HTML解析
↓
执行JS
↓
继续HTML解析
JS执行完后
不会:
重新解析HTML
而是:
从中断位置继续解析
六、JS修改DOM会发生什么
例如:
div.style.width = '300px'
浏览器:
修改DOM
↓
标记Dirty
↓
JS执行结束
↓
统一更新
后续可能触发:
Style
↓
Layout
↓
Paint
↓
Composite
七、重排(Reflow)
本质:
重新Layout
需要重新计算:
位置
大小
常见触发
width
height
padding
margin
font-size
appendChild
removeChild
流程
Layout
↓
Paint
↓
Raster
↓
Composite
代价最大。
八、重绘(Repaint)
本质:
重新Paint
布局没变。
外观变了。
常见触发
color
background
border-color
流程
Paint
↓
Raster
↓
Composite
不触发Layout。
九、强制同步布局(Forced Reflow)
错误写法:
div.style.width = '300px'
console.log(div.offsetWidth)
浏览器发现:
布局还没算
你却要读结果
立即执行:
Layout
这叫:
Forced Reflow
性能很差。
十、为什么transform性能最好
错误:
left:100px
top:100px
width:200px
触发:
Layout
Paint
Raster
Composite
推荐:
transform: translateX(...)
opacity: 0.5
只触发:
Composite
流程:
已有Texture
↓
GPU直接变换
↓
显示
十一、线程与阶段对应关系(面试必背)
Main Thread
├─ HTML Parse
├─ Style
├─ Layout
├─ Paint
└─ Layerization
Raster Threads
└─ Raster
Compositor Thread
└─ Composite
GPU
└─ Draw Frame
十二、一句话总结
浏览器先解析HTML和CSS,构建DOM树和CSSOM树,
然后进行样式计算(Style)和布局(Layout),
接着生成绘制指令(Paint),
再进行图层构建(Layerization),
由光栅化线程把绘制指令转换为位图或纹理(Raster),
合成线程组织各个图层生成待显示帧(Composite),
最后GPU完成图层混合和渲染,
将最终帧输出到屏幕。
面试时记住这一条主线即可:
HTML
↓
DOM
↓
CSSOM
↓
Style
↓
Layout
↓
Paint
↓
Layer
↓
Raster
↓
Composite
↓
GPU
↓
Screen