浏览器的渲染流程
-
解析HTML,生成DOM树。
在解析HTML的过程中,会启动一个预解析线程,率先下载HTML中外部的CSS和JS文件,当主线程解析到link位置,如果外部CSS文件没有下载好,主线程不会等待,继续解析后续的HTML。因为下载和解析CSS的工作在预解析线程中,所以CSS不会阻塞HTML解析。CSS解析最终生成CSSOM树。
当主线程解析到script位置,会停止解析HTML,等待JS文件下载完成,并将全局代码解析执行完成后,才能继续解析HTML。因为JS代码执行可能修改DOM树,所以DOM树的生成必须暂停。这就是JS会阻塞HTML解析的根本原因
-
样式计算
主线程会遍历得到的DOM树,依次为每个节点计算出最终样式。最终得到一颗带有样式的DOM树
-
布局
主线程遍历带有样式的DOM树,根据DOM节点的计算样式计算出一个布局树。布局树上每个节点有他在页面上的x,y坐标及盒子大小的具体信息
-
分层
主线程需要遍历整棵布局树来创建一棵层次树
-
生成绘制指令
主线程会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。生成绘制指令后,主线程将每个图层的绘制信息提交给合成线程,剩余工作由合成线程完成
-
分块
合成线程将每个图层进行分块,划分为更多的小区域,分块的工作交给多个线程同时进行,会从线程池中拿取多个线程来完成分块工作
-
光栅化
将每个块变成位图,就是确认每一个像素点的rgb信息。光栅化的操作不由合成线程来做,而是由合成线程将块信息交给GPU进程,以极高的速度完成光栅化。此过程用到GPU加速
-
绘制
当所有图块被栅格化后,合成线程会拿到每个层,每个块的位图,从而生成一个个指引(quad)信息.合成线程计算出每个位图在屏幕上的位置,交给GPU呈现。
transform发生在合成线程,与渲染主线程无关,所以transform效率高
渲染主线程 解析 - 样式计算 - 布局 - 分层 - 生成绘制指令 -
合成线程 分块 - 光栅化 - 绘制 - ⬇
GPU
reflow
本质是重新计算布局树,为了避免连续多次操作导致布局树反复计算,浏览器会合并这些操作,当JS代码全部完成后统一计算,所以改动属性造成的reflow是异步完成的。 正因为如此,当JS获取布局属性时,可能无法获取到最新的布局信息,所以决定获取属性时立即reflow
repaint
本质是重新根据分层信息计算了绘制指令,也就是影响了上方 生成绘制指令 这一步
为什么transfrrm效率高
transfrom既不影响布局,也不影响绘制指令,影响的只是渲染流程的最后一个 绘制 阶段,而绘制阶段在合成线程中,几乎不会影响渲染主线程