浏览器运行原理(三)

67 阅读4分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

渲染进程是如何工作的

渲染进程几乎负责 Tab 内的所有事情,渲染进程的核心目的在于转换 HTML CSS JS 为用户可交互的 web 页面。渲染进程中主要包含以下线程:

1628520325(1).png

  1. 主线程 Main thread
  2. 工作线程 Worker thread
  3. 排版线程 Compositor thread
  4. 光栅线程 Raster thread

后文我们将逐步介绍不同线程的职责,在此之前我们先看看渲染的流程

1、构建DOM

当渲染进程接收到导航的确认信息,开始接受HTML数据时,主线程会解析文办字符串为DOM。

渲染html为DOM的方法有HTML Standard定义。

2、加载次级的资源

网页中常常包含诸如图片,CSS,JS等额外的资源,这些资源需要从网络上火车cache中获取,主进程可以在构建DOM的过程中会逐一请求它们,为了加速preload scanner 会同事运行,如果在html中存在 等标签,preload scanner会把这些请求传递给Browser process中的network thread进行相关资源的下载。

3、JS的下载与执行

当遇到

不过开发者其实也有多种方式来告知浏览器如何应对某个资源,比如说如果在script标签上添加了async或defer等属性,浏览器会异步的加载和执行JS代码,而不会阻塞渲染。

4、样式计算

仅仅渲染DOM还不足以获知页面的具体样式,主进程还会基于CSS选择器解析CSS获取每个节点的最终的计算样式值,即使不提供任何CSS,浏览器对每个元素也会有一个默认的样式

1628521032(1).png

5、获取布局

想要渲染一个完整的页面,处理获知每个节点的具体样式,还需要获知每个节点在页面上的位置,布局其实就是找到所有元素的集合关系的过程,其具体过程如下:

通过遍历DOM及相关元素的计算样式,主线程会构建出包含每个元素的坐标信息及盒子大小的布局树,布局树和DOM树类似,但是其中只包含页面课件的元素,如果一个元素设置了display:none,这个元素不会出现在布局树上,伪元素虽然在DOM树上不课件,但是在布局树上是可见的。

1628521056(1).png

6、回执各元素

即使知道了不同元素的位置及样式信息,我们还需要知道不同元素的回执先后吮吸才能正确绘制出整个页面,在绘制阶段,主线程会遍历布局树以创建绘制记录,绘制记录可以看做是记录各元素绘制先后先后的笔记。

1628521078(1).png

7、合成帧

熟悉PS等绘图软件的同学肯定对图层这一概念不陌生,现代Chrome其实利用了这一概念来组合不同的层。

符合是一种分割页面为不同的层,并单独栅格化,随后组合为帧的技术,不同层的组合由compositor线程(合成器线程)完成

主线程会遍历布局树来创建层树,添加了'will-change'CSS属性的元素,会被看作单独的一层。

1628521105(1).png

你可能会想给每个元素都添加上'will-change',不过组合过多的层也许会比在每一帧都栅格化页面中的某些小部分更慢。

一旦层树被创建,渲染顺序被确定,主线程会把这些信息通知给合成器线程,合成器线程会栅格化每一层,有的层可以达到整个页面的大小,因此,合成器线程将把它们分成多个磁贴。并将每个磁贴发送到栅格线程,栅格线程会栅格化每个磁贴存储在GPU显存中

1628521139(1).png

一旦磁贴被光栅化,合成器线程会手机成为绘制四边形的磁贴信息以创建合成帧

合成帧随后会通过IPC消息传递给浏览器进程,由于浏览器的UI改变或者其他拓展的渲染进程也可以添加合成帧,这些合成帧会被传递给GPU用以展示在屏幕上,如果滚动发生,合成器线程会创建另一个合成帧发送给GPU.

1628521160(1).png

合成器的优点在于,其工作无关主线程,合成器线程不需要等待样式计算或者JS执行,这就是为什么合成器先关的动画最流畅,如果,某个动画设计到布局或者绘制的调整,就会设计到主线程的重计算,自然会慢很多。