← 返回笔记
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