首先,同步背景为Chrome浏览器,它的多进程架构如下:
- 浏览器(浏览器主进程)
- GPU进程
- NetWork Service(网络进程)
- Storage Service (存储进程)
- Audio Service (音频进程)
- 扩展进程
- 渲染进程(一般情况下,为每个标签启用单独渲染进程)
当浏览器接受完成HTML文件时,我们所要讨论的大部分情况是发生在渲染进程中的。
a. 构建DOM树
渲染引擎 将HTML解析为 浏览器可以理解的DOM树。
b.样式计算
- 转换:CSS文本 -> styleSheets(使浏览器可以理解)
- 属性值标准化:如将rem统一转为px
- 计算每个节点具体的样式:根据CSS层叠、CSS继承规则 -> Computed Style
c.布局阶段
- 创建布局树 LayoutTree(只包含可见元素节点的树):DOM树 + ComputedStyle -> 布局树
- 布局计算:计算节点坐标位置,保存在布局树中。
d.分层
- 生成图层树 LayerTree,页面是由图层叠加合成的(可以通过Chrome Layer工具查看页面图层)
- 形成新图层的条件?有层叠上下文属性的元素;需要剪裁的地方(滚动条也是图层)
e.绘制
渲染引擎对图层树中的每个图层进行绘制。
把一个图层的绘制拆分为很多小的绘制指令,比如在指定位置绘制一条黑色的线/黄色的矩形。
f.分块
视口viewport(用户可以看到的页面的一部分),合成线程(在h中提到)按照视口附近的图块来优先生成位图。
g.光栅化(栅格化)
栅格化是指将图块转换为位图,所以生成位图的操作是由栅格化来执行的。
栅格化是在栅格化线程中完成的,渲染进程维护一个栅格化线程池。
通常栅格化线程会使用GPU加速栅格化生成,所以存在跨进程操作,生成的位图是保存在GPU进程中的
h.合成
实际的绘制任务是由渲染进程中的合成线程来执行的,合成线程(将图层分为图块。
一旦所有图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
可以参考以下图片理解以上整个渲染流程: