Jeffrey · Chiang

浏览器渲染原理

渲染流程分:HTML解析、样式计算、布局、分层、绘制、分块、光栅化、呈现

解析HTML

CSS & JS

先启动预解析过程,提前下载引用的外部样式和脚本 正式解析过程中,依次解析html字符串,计算css,执行js:

  • 外部样式的下载解析由于运行不同线程之上且有自己的产出结果,所以样式的解析不会阻塞html解释流程
  • 全局的js代码有可能会修改已解析的dom,且最终的执行结果可能需要反馈到dom树上,所以外部js的下载和执行需要暂停html的解析,

解析html产出

DOM树 + CSSOM树

样式计算 Recalculate Style

根据不同优先级叠加所有样式后,遍历整个dom树,并为每个节点计算样式,其中预设的颜色、单位会转换为绝对单位、标准颜色值

样式计算产出

带样式的DOM树

布局

遍历DOM树,为所有可见节点计算几何信息,添加伪元素及匿名行/块拿,产生布局树, 由于存在隐藏的dom节点,以及伪元素和匿名行/块盒的存在,布局树与DOM树并不一一对应.

布局阶段产出

布局树

分层

出于性能考虑,避免后续修改导致重新执行前面的步骤,需要对之前阶段的产出分层

浏览器开发者工具中的Layers tab 可查看一个页面的分层信息

可以通过为指定的dom添加will-change样式属性,告知浏览器后续需要变更的dom样式,由浏览器决定是否需要将dom单独分层

div{
    will-change: transform;
}

绘制 PAINT

根据分层结果,为每层生成绘制指令,生成绘制指令集

绘制主线程工作结束,后续工作由其他线程完成

分块 TILE

由合成线程(Compositor)负责分块工作,根据每一层最新的绘制指令集

光栅化

由GPU加速线程,合并同属一块不同图层绘制指令,形成像素点数据,

呈再

由GPU线程根据位图信息,完成最终呈现

扩展

reflow

当进行了会影响了布局树的操作后,重新计算布局树,会引发layout.

为避免多次操作导致反复计算布局树的操作,浏览器采取防斗策略,会合并相关操作,最后统一计算,reflow是异步完成的,为避免js获取布局属性时,可能无法获取到最新的布局信息等问题,当获取属性时,立即reflow

repaint

当改动了可见样式:如字体、颜色等不影响布局的样式属性后,需要重新计算绘制指令

由于布局信息也属于可见性属性,所以reflow一定会引起重绘

transform

transform作用于渲染流程的最后阶段,即合成线程内的呈现阶段,即不会引发回流也不会造成重绘