现代浏览器的渲染流程

2023-05-30 09:57:55 浏览数 (2)

当浏览器的网络线程收到html文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。

在事件循环机制的作用下,渲染线程取出消息队列中的渲染任务,开启渲染流程Renderer(线程是Theread)。

整个渲染流程分为两大阶段,八大步骤,分别是:html解析(HTML Parse)、样式计算(Computed Style)、布局(Layout)、分层(Layer)、绘制(Paint)、分块(Tiling)、光栅化(Raster)、画(Draw),每个结算都有明确的输入输出,上一个阶段的输出会成为下一个阶段的输入。这样整个渲染流程就形成了一个完整的流水线。

一、html解析

解析过程中遇到css解析css,遇到JS执行JS。为了提高解析效率,浏览器在开始解析前,会开启一个预解析的线程,率先下载html中的外部css和js文件

如果主线程解析到link标签时,因为外链的css文件尚未下载解析好,主线程不会等待,继续解析后续的html,因为下载和解析css是在预解析线程进行,这就是css不会堵塞html的根本原因

如果主线程解析道script标签时,会停止解析html,进而等待js文件下载完成,并将全局代码解析、执行完成后,才能继续解析hmtl。这是因为js代码的执行过程中可能会修改当前下载好的dom树,所以dom的生成必须暂停,这也就是js会堵塞html解析的根本原因。

这一步完成之后,会得到DOM树和CSSDOM树,浏览器的默认样式、内部样式、外部样式、行内样式等均会在CSS树中。

二、样式计算

主线程根据第一步得到的DOM树和CSS树,依次为树中的每个节点计算出它最终的样式,从而生成带有样式的DOM树,可以了理解为将CSS树绑定到DOM树上。在这个阶段中,很多预设值会变为绝对值,如red变成rgba,em变成px等。总之,在这个阶段中,会计算元素的层叠、继承,以及盒模型等等。

三、布局

一次遍历DOM树中的每一个节点,计算每个节点的几何信息,例如:节点的宽高、位置等。很多时候,从而生成布局树。,DOM树和布局树不是一一对应,如:一个节点display: none的节点没有几何信息,从而不会生成布局树,或者使用伪元素选择器,虽然DOM树中没有这些伪元素信息,但却有几何信息,从而会生成布局树中。

四、分层

主线程使用一到负责的策略,将布局进行分层,在这个阶段中,跟堆叠上下文有关的属性会影响分层,如:z-index,opacity、transform、滚动条等。will-change可以更大程度的影响分层结果分层的好处在于,将来某个层改变后,仅仅会对该层进行后续单独戳里,从而提升效率。每一层会有很多绘制指令

五、绘制

主线程回味每隔层单独产生绘制指令集,用于描述着一层的内容该如何画出来

六、分块

完成绘制之后,主线程将每个图层的信息提交给合成线程Compositor,剩余工作将于合成线程完成。合成线程首先会对每个图层进行分块,将其划分为更多的小区域,即合成线程启动多个分块线程CompositorTile。它会从线程池中取出更多线程来完成分块工作。

七、光栅化

分块完成后,进入光栅化阶段。

合成线程会将信息交给GPU进程,以极高的速度完成光栅化。

GPU进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的快。

光栅化的结果,就是一块块的位图(包含像素点等信息)

八、画

合成线程拿到每个层、每个块的位图后,会生成一个个【指引quad】信息

指引会标示出每个位图应该画到屏幕的哪个位置,以及会考虑到渲染、缩放等变形。

变形发生在合成线程,与渲染主线程无关,也就是transform做动画性能高的根本原因。

合成线程会把quad提交给GPU进程,由GPU进程产生系统调用,提交给GPU硬件显卡,完成屏幕成像。

面试真题

a. 什么是reflow

重绘。修改跟几何信息相关的信息,会影响到第二步及以后的步骤。如:修改宽高、定位left等。

reflow本质就是重新计算layout树,需要重新计算布局树,会引发layout

为了避免连续的多次操作导致布局反复计算,浏览器会合并这些操作,当js代码全部完成后再进行统一的计算,所以,改动属性造成的reflow时异步完成的,进而导致js获取布局属性时,就可能造成无法获取到最新的布局信息。

浏览器在反复权衡,最终决定获取属性立即reflow。

当然,js获取元素的几何属性,也会导致reflow。

b. 什么是repaint

repaint的本质就是重新根据分层信息计算绘制指令。

回流,修改跟几何信息无关的信息,如:颜色等。这个阶段可能会影响分层,也可能不会,如:如果修改z-index、opacity、transform可能就会导致分层。如果单纯修改color、background咋不会,但肯定会导致绘制这一步,因为要产生绘制指令。

所以,reflow肯定会引起repaint,但是repaint不会引起reflow。

c. 为什么transform的效率高。

transform不会影响布局,也不会影响绘制指令,值会影响渲染流程最后的draw阶段。

draw阶段在合成线程中,所以transform的变化不会影响渲染主线程。两者不是作用在同一个线程中。(滚动条也不是在渲染主线程中,所以有时页面死循环了,页面仍旧可以滚动一样的道理)

0 人点赞