浏览器的网络线程获取到 HTML 后,产生一个渲染任务,交给渲染主线程的消息队列,
在事件循环机制的作用下,渲染主线程取出渲染任务,开始以下 8 个主要的渲染流程:
事件循环机制详见《浏览器渲染进程模型——事件循环》
- 解析 HTML:
- 主线程遇到 css 解析 css,遇到 js 执行 js。
- 为提高效率,解析前浏览器还会开启一个
预解析线程,用于提前下载外部的 css 和 js 文件并解析,因为是预解析线程所以 css 不会阻塞主线程,但 js 可能会修改页面所以阻塞主线程。 - 完成后生成
dom和cssom树
- 样式计算 style:
- 主线程遍历 dom 树,计算最终样式,如预设值变成绝对值、相对单位变成绝对单位等。
- 完成后生成
带样式的dom树
- 布局 layout:
- 主线程遍历带样式的 dom 树,计算几何信息,如宽高,相对
包含块的位置。 - 遍历完后生成布局树,不会和 dom 树一一对应,因为没有几何信息的 dom 节点不会生成到布局树,而 dom 节点中不存在的伪元素若有几何信息则会生成到布局树,还有布局树中额外添加的
匿名行盒、匿名块盒等都会导致不和 dom 树一一对应。 - 完成后生成
布局树
- 分层 layer:
- 主线程使用一套复杂的策略对整个布局树进行分层,实现按需修改提升效率。
- 滚动条、堆叠上下文、transform、opacity、
will-change等属性会影响分层结果。 - 完成后生成
多层结构
- 绘制 paint:
- 主线程为每个层单独产生绘制指令集,用于描述该层内容如何画出来,类似 canvas 原理。
- 完成后生成
各层的指令集
主线程任务结束,后续由其他线程完成。
- 分块 tiling:
- 合成线程对每个层进行矩阵分块,从而可以优先显示视口区域。
- 此过程会从
线程池分配多个分块器进行多线程同时工作。 - 完成后生成
各层的矩阵块
- 光栅化 raster:
- 合成线程将块信息交给
GPU进程,以极高速度完成光栅化。 - 此过程也会分配多个线程,并优先光栅化视口区域。
- 完成后生成
各层的位图(包含像素信息)
- 画 draw:
- 合成线程根据各层的位图生成一个个的
指引quad信息。 - 指引会标识每个位图应该画到屏幕哪个
像素位置,以及 transform 变形信息。 - transform 变形在此步骤才开始计算,把位图通过
数学矩阵变换来实现各种效果。 - 完成后生成
指引quad
合成线程把全部指引提交给 GPU 进程,后续由 GPU 进程完成。
GPU 进程拿到指引 quad 后,产生系统调用,提交给 GPU 硬件,完成最终的屏幕成像。