浏览器渲染流程


HTML/CSS/JS

浏览器接收 这三种文件,渲染出页面

HTML:HyperText Marked Language, 超文本标记语言, 标记 和 文本 组成
CSS: Cascading Style Sheets, 层叠样式表, 选择器 和 属性组成
JS: Javascript, 解释型编程语言, 能让页面’动’起来

渲染流水线分为以下8个子阶段:
构建DOM树 样式计算 布局阶段 分层 绘制 分块 光栅化 合成

构建DOM树

创建出节点

1.HTML被转换为浏览器能理解的结构,DOM树

根据HTML中的 层次结构,将HTML解析为 具有父子节点关系的DOM树
浏览器输入document可以看到DOM树结构

样式计算

计算出每个节点的样式

2.将CSS转换为浏览器能理解的结构,styleSheets

CSS三个来源link外部CSS文件,style标签内的CSS,元素style属性内的CSS
该结构具备查询和修改功能
浏览器输入document.styleSheets查看

3.转换样式表中的属性值,使其标准化

如:2em,blue,bold等属性值

4.计算出DOM树中每个节点的具体样式(继承和层叠)

继承:子节点继承父节点样式,层叠:一个DOM节点合并多个来源属性值的优先级

布局阶段

计算出DOM树中 可见元素 的 几何位置

5.创建布局树

构建只含可见元素的布局树,如 head标签下的全部内容全不可见

6.布局计算

进行布局操作的时候,会把布局运算的结构又写回布局树
所以布局树既是输入又是输出,这是布局阶段一个不合理的地方
Chrome团队正在重构代码,下一代布局系统叫LayoutNG,试图清晰分离输入输出,布局算法更加简单

分层

  1. 渲染引擎为特定节点生成专用图层,并生成图层树(layerTree)

    一个图层可包含多个节点,满足以下情况之一会生成图层
    拥有层叠上下文属性的元素会单独一层(position:fixed,z-index,opacity:0.5)
    被裁剪过的元素,如 div盒子长宽小于内容长宽

  2. 绘制列表 为每个图层生成绘制列表,交给合成线程

    渲染引擎将一个图层的绘制分成多个绘制指令,组成待绘制列表
    绘制列表 只是用来记录 绘制顺序 和 绘制指令 的列表,

光栅化

主线程将绘制列表提交给合成线程,实际绘制由 渲染引擎 中的 合成线程 来完成
视口(viewport):用户能看见的页面部分,
图块(tile):栅格化的最小单位,256X256或512X512,合成线程 将图层分化而来
栅格化/光栅化: 将 图块 转化为 位图
快速栅格化/GPU栅格化: 栅格化在专门的 栅格化线程池 中执行, 通常使用GPU生成位图,
结果的位图数据 在GPU内存中,这就涉及了跨进程操作,渲染进程 与 GPU进程

  1. 合成线程 将图层分为图块

  2. 图块在 栅格化线程池中 被栅格化 为位图

合成

  1. 合成线程 在所有图块被光栅化后, 生成 绘制图块命令DrawQuad,提交 浏览器线程

  2. 浏览器线程, viz组件 接收 DrawQuad命令, 将页面内容绘制在 内存 中,最后将 内存 显示在屏幕上

总结

  1. 渲染进程 将HTML转换为 DOM树
  2. 渲染引擎 将CSS转换为 styleSheets,计算出 DOM节点 的 样式
  3. 布局树 被创建,并 计算布局信息
  4. 图层树 被创建,由 布局树 分层而来
  5. 绘制列表 被根据每个图层生成, 并提交给 合成线程
  6. 合成线程 将图层 分为 图块,并在 光栅化线程池 中将图块转换为 位图
  7. 合成线程 发送 绘制图块命令DrawQuad 给 浏览器进程
  8. 浏览器进程 根据 DrawQuad 生成页面,并 显示 在显示器上

重排 重绘 合成

CSS文件的下载阻塞DOM树的合成

浏览器接收到HTML页面第一批数据的时候,DOM解析器开始工作

JS脚本会阻塞DOM渲染
JS外部脚本也会阻塞DOM渲染
JS脚本访问了元素样式,则会等待样式文件下载,从而阻塞DOM渲染
如果,解析过程遇到内部JS脚本非文件,会暂停解析,执行JS脚本,再继续解析;
如果,解析过程遇到外部JS脚本文件,会暂停解析,下载并执行JS脚本,再继续解析;
如果,解析过程遇到JS脚本,会暂停解析,执行JS脚本,
如果,此JS脚本访问了某元素样式,会暂停JS执行,等待样式下载,才继续执行JS.


文章作者: 罗紫宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗紫宇 !
  目录