浏览器渲染流程

2 阅读3分钟

浏览器的渲染流程:

  1. HTML解析
  2. 计算样式
  3. 布局
  4. 分层
  5. 生成绘制指令
  6. 分块
  7. 光栅化
  8. 绘制

一、HTML解析(渲染主线程)

输入:html字符串
  • 首先拿到的是一个html的字符串,需要通过令牌化(Tokenizing)将字符转换为HTML标签(如 <div><p>
  • 渲染主线程根据解析标签的层级关系来构建DOM树(Document Object Model)
  • 遇到<script>标签会暂停HTML解析,等待js下载并执行完成后再继续解析(除非标记为asyncdefer),因为js文件可能会对dom元素进行修改,要构建正确结构的DOM树,就要等待js执行完成。所以:js的下载和执行会阻塞渲染主线程
  • 遇到<link> 或 <style> 会触发 CSS 解析,将CSS样式规则构建为CSSOM树(CSS Object Model),css的解析会阻塞渲染
  • css文件的下载在预解析线程,不会阻塞渲染主线程
输出:DOM树和CSSOM树

二、计算样式(渲染主线程)

输入:DOM树和CSSOM树
  • 拿到了DOM树和CSSOM树,要把样式给对应的dom节点安上,所以合并DOM和CSSOM,生成渲染树(Render Tree)
  • 每个DOM节点的所有样式都计算完,在这个过程中,预设值为变成绝对值,如 red 变成 rgb(255,0,0) ,相对单位变成绝对单位,如 em 变成 px
  • 会过滤掉display为none的DOM节点
输出:渲染树(Render Tree)

三、布局(渲染主线程)

输入:渲染树(Render Tree)
  • 有了样式信息,但是还不能绘制出来,因为还不知道具体的位置信息和尺寸信息
  • 遍历渲染树的每个节点,根据 CSS 盒模型、浮动、定位等规则,计算每个节点的精确几何信息,如具体位置的x,y坐标,宽度、高度等。
  • 当修改了节点的几何属性,如大小、位置,就需要重新计算布局,这个过程也叫做回流或者重排(reflow)
  • 获取节点的几何属性时,如 offsetWidth / getBoundingClientRect/clientWidth强制重排
输出:布局(layout)

四、分层(渲染主线程)

输入:布局(layout)
  • 将页面进行分层,之后某个层变化时,就可以单独更新这一个图层,从而避免了全页面的更新,提高效率。
  • 滚动条一般会单独分层
  • 影响分层的属性 : will-change ,z-indexposition:fixed/absolute +z-index 等
输出:多个分层

五、生成绘制指令(渲染主线程)

输入:多个分层
  • 为每一个分层单独绘制对应的指令集,用来描述当前图层该如何绘制
输出:多个绘制指令集

六、分块(合成线程)

输入:多个分层
  • 大尺寸图层(如全屏滚动区域)会占用大量的GPU内存,消耗资源效率低
  • 合成线程会调用多个线程把每个分层都分成更小的(Tile),通常为256x246或者512x512像素
输出:多个块

七、光栅化(光栅化线程+GPU)

输入: 多个块
  • 光栅化将每个块转成位图,光栅化线程处理分块的像素填充,启用GPU加速光栅化,GPU会优先处理靠近视口区域的块
输出:多个位图

八、绘制(合成线程+GPU)

输入:多个位图
  • 合成线程会根据所有的位图,计算QUAD信息,包括位置和几何变换等,合成最终屏幕图像,随后交给GPU渲染页面
  • transform等变形就发生在合成线程,所以不会阻塞渲染主线程,性能更好
输出:屏幕显示

欢迎指正!