浏览器原理:3.渲染流程详解

由于渲染机制过于复杂,所以渲染模块在执行过程中会被划分为很多子阶段,输入的HTML经过这些子阶段,最后输出像素。我们把这样的一个处理流程叫做渲染流水线

按照渲染的时间顺序,流水线可以分为

  • 构建 DOM 树

  • 样式计算

  • 布局阶段

  • 分层

  • 绘制

  • 光栅化

  • 合成

    重点关注每个阶段的这些内容

    • 其输入的内容
    • 处理过程
    • 输出的内容

构建 DOM 树

为什么要构建 DOM 树

  • 因为 浏览器无法直接理解和使用 HTML ,所以需要将HTML转换为浏览器能够理解的数据结构 —— DOM 树

DOM是保存在内容中树状结构,可以通过 JS 来查询或者修改其内容,在控制台输入 document 即可查看

在生成dom树后,已经有了页面的基本结构,但样式仍然不知道,所以下一步是样式计算

样式计算

样式计算的目的是为了计算出 DOM 节点中每个元素的具体样式

  • 把 CSS 转换为 浏览器能够理解的数据结构 (即编译 CSS)

    CSS样式来源

    • link
    • style
    • 内嵌style样式

    浏览器会将CSS编译为 styleSheets

    document.styleSheets 在控制台查看编译生成的 stylesheets

  • 转换样式表中的属性值,使其标准化
    即许多分开写的css属性,能写成一个会直接合并成一个,例如:background-color属性 会被直接合并到 background属性 上面

  • 计算出 DOM 树每个节点的具体样式

    根据CSS的继承规则以及层叠规则进行计算

    层叠规则,是一个定义了如何合并来自多个源的属性值的算法,即怎样确定属性值的优先级

布局阶段

目前,已经有了页面的内存数据,DOM树,接下来就需要计算出 DOM 树的 可见元素的 几何位置,这个计算过程叫做布局

Chrome在布局阶段主要完成:创建布局树和布局计算

  • 创建布局树

    浏览器主要完成遍历 DOM 树中的所有可见节点,并把这些节点加到布局树中

    DOM树中的不可见元素,没有包含到布局树中

  • 布局计算

    计算出每个元素的几何坐标位置,并将这些信息保存在布局树中

    在执行布局计算的时候,会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome团队正在重构布局代码,下一代布局系统叫LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单。

分层

因为页面中有很多复杂的效果,如一些复杂的3d变换、页面滚动、或者使用z-index做 z 轴排序等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一颗对应的图层树,类似PS里面的那个图层

可以在 Chrome 开发者工具里面的,layer 看见具体效果

通常情况下,并不是布局树的每一个节点都包含一个图层,如果一个节点没有对应的层,那么这个节点就属于父节点的图层,即不管怎样所有节点都会直接或者间接地属于某一个图层

怎样的元素具有单独的图层

  • 拥有层叠上下文属性的元素会被提升为单独的一层

    层叠上下文属性:明确定位属性的元素、定义透明属性的元素、使用CSS滤镜的元素等都拥有

  • 需要被裁剪的地方也会被创建为图层

    裁剪:当div里面的内容溢出的时候,就产生了裁剪,渲染引擎会把一溢出的部分裁剪,把剩下的部分用于显示在div区域

  • 如果出现滚动条,滚动条也会被提升为单独的层

图层绘制

渲染引擎实现图层的绘制,会把一个图层的绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表

栅格化操作

绘制列表只是用来记录绘制顺序和绘制指令的列表,而实际上绘制操作是由渲染引擎中的合成线程来完成的

一般来说,为了提高效率,渲染不会渲染完所有图层内容,基于这个原因,合成线程会将图层划分为一块一块的图块。

然后合成线程会按照视口附近的图块来优先生成位图(即由像素组成的图像),生成实际位图的操作是由栅格化来执行的。

栅格化就是将图块转换为位图,图块是栅格化执行的最小单位,渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池中进行的

通常,栅格化过程都会使用GPU来加速生成,使用GPU生成位图的过程叫快速栅格化,或者GPU栅格化,生成的位图被保存在GPU内存中。

合成和显示

一旦所有图块都被栅格化,渲染进程中的合成线程就会生成一个绘制图块的命令 —— DrawQuad 然后将该命令提交给浏览器进程

浏览器进程由一个叫 viz 的 组件,用来接受合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上

渲染流水线总结

在这里插入图片描述

相关概念(重排、重绘、合成)

  • 重排

    重排就是,通过修改样式,触发了渲染流程中的生成布局树和图层及后面的所有过程

  • 重绘

    重绘就是,通过修改样式,触发了渲染流程中的生成绘制列表及后面的过程,即没有触发生成布局树和图层

  • 合成

    合成就是,通过修改样式,触发了合成线程中的所有操作,即没有触发生成绘制列表及前面的操作

在优化Web性能的方法中,减少重绘、重排是一种很好的优化方式,以及动画尽量用CSS实现

  • 触发重排,重绘的操作尽量放在一起,比如改变dom高度和设置margin分开写,可能就会触发发两次重排
  • 通过虚拟dom层计算出操作总的差异,一起提交给浏览器。之前还用过createdocumentfragment来汇总append的dom,来减少触发重排重绘次数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值