浏览器渲染页面时,渲染进程做了什么

浏览器通过网络进程,如果最后解析到的数据格式是text/html,那么浏览器则会继续进行渲染流程。
每一个页面回对应一个渲染进程,每打开一个页面浏览器就会配套一个新的渲染进程。当渲染进程拿到浏览器进程传过来的数据后就可以开始进行渲染了。
在这里插入图片描述
这里我们把渲染进程依据时间顺序分成以下几个步骤。构建DOM树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成

1.构建dom树

浏览器无法直接理解html,所以需要将html转换成浏览器能够理解的结构,即dom树。

2.计算样式

计算样式的目的是得到dom节点中每个元素的样式,需要以下几步。

  • 将css转换成浏览器能理解的结构,styleSheets。
  • 转换样式表中的属性值,使其标准化。
  • 计算出dom节点中每个元素的样式。

关于如何计算出dom节点中每个元素的样式,这涉及到CSS的继承规则和层叠规则了。
首先是CSS继承,CSS继承就是每个DOM节点都包含有父节点的样式,就像下图中的content_views,除了本身的样式,还继承了父节点的样式。
在这里插入图片描述
至于层叠,层叠是CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。
我们可以在浏览器控制台element的Computed中看到对应dom最后计算得到的样式。
在这里插入图片描述

3.布局阶段

有了dom树跟对应的样式,接下来需要计算出dom树中可见元素的位置,这个动作就是布局。

创建布局树

在页面中,不是所有dom节点都能看见的,像head,script,meta以及display:none的节点等。所以在显示之前,我们还要额外地构建一棵只包含可见元素布局树
为了构建布局树,浏览器大体上完成了下面这些工作:

  • 遍历DOM树中的所有可见节点,并把这些节点加到布局中;
  • 而不可见的节点会被布局树忽略掉;
计算布局

在执行布局操作的时候,会把布局运算的结果重新写回布局树中。每个元素的具体位置信息。

4.分层

页面中有很多复杂的效果,如一些复杂的3D变换、页面滚动,z-index等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树。
通过控制台的Layers,可以清晰地看到页面带分层。
在这里插入图片描述
可见浏览器的页面实际上被分成了多个层面,最后叠加成我们最后看到的页面。
布局树跟图层树的关系如下
在这里插入图片描述
一般情况下,不是每个节点都会包含一个图层,某个节点如果没有自己的图层那么它就会丛书父节点的图层,像上图中的span。想要生成新图层的话需要满足以下任意一个条件。

  • 拥有图层上下文属性(z-index,position,opacity等)
  • 需要裁剪的地方也会生成新图层
    关于什么是裁剪,比如我们写了一个dom,给了固定宽高,里面的内容超出了它的大小,这时候它的内容就会被渲染引擎裁剪一部分显示在dom中
<body>
    <div>111111111111111111</div>
</body>
<style>
div {
    background-color: #666666;
    width: 50px;
    height: 50px;
    overflow: auto;
}
</style>

在这里插入图片描述

5.绘制

图层树构建完成后,渲染引擎会对每个图层进行绘制。渲染引擎会先把一个图层的绘制内容分成多个部分,将其组成一个绘制列表。我们可以通过控制台的Layers,选择对应的图层查看其绘制列表和过程
在这里插入图片描述

6.分块

绘制列表只是用于记录绘制顺序和指令,实际上做绘制的是渲染引擎中的合成线程操作的。主线程中绘制列表准备好后会将其提交给合成线程。
合成线程首先会将图层进行分块,因为一个页面往往一个屏幕的可见区域是装不下的,浏览器没必要一次性将整个图层绘制出来,这时候就会先将其分块。合成线程再优先对可见区域附近的图块进行绘制生成位图(是由像素的单个点组成的图像)。

7.光栅化

实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的。
栅格化过程都会使用GPU来加速生成,使用GPU生成位图的过程叫快速栅格化,或者GPU栅格化,生成的位图被保存在GPU内存中。
GPU操作是运行在GPU进程中,如果栅格化操作使用了GPU,那么最终生成位图的操作是在GPU中完成的,这就涉及到了跨进程操作。具体形式你可以参考下图:
在这里插入图片描述

8.合成

一旦所有图块都栅格化完成,合成线程(渲染进程)就会生成一个DrawQuad命令告知浏览器进程,浏览器进程里面有一个叫viz的组件,用来接收合成线程发过来的DrawQuad命令,然后根据DrawQuad命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。至此渲染流程完毕。

总结

整个渲染流程可以概括如下
在这里插入图片描述

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

拓展

回流重绘

回到我们老生常谈的回流,重绘。在了解了页面的渲染流程之后相信会对回流重绘会有更好的理解。
当我们修改了dom的宽高导致回流,需要更新完整的渲染流水线,所以开销也是最大的。从整个流程上来看,它不需要进行构建dom树,而是从构建styleSheets这一步修改其更改的样式后继续走完整个渲染流程,而重绘呢。
当我们修改了dom的颜色导致重绘,渲染流程也不需要重新构建dom树,但还是会修改styleSheets,但是由于没有改变dom的几何属性会跳过布局阶段,再走完成功渲染流程,所以其消耗比回流小

合成

除了回流重绘,还有一种操作叫做合成。它不需要绘制与合成,所以渲染引擎将跳过布局跟绘制,执行最后的合成操作即可。当我们在css中使用了transform便可以达到这种效果,直接在非主线程上执行合成动画操作。所以相对于重绘和重排,合成能大大提升绘制效率

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值