在浏览器运行原理的博文中我没有仔细讲渲染器进程是如何工作的。现在来谈谈渲染器进程接收到数据后是如何渲染页面的?本文会出现主线程和合成器线程的概念
无论是DOM还是CSSOM,数据都是要经过Bytes→characters→tokens
→nodes(节点)→object model(对象模型)
这个过程。这是由渲染器进程中的线程进行。
解析的数据有:HTML文件、CSS文件。
我们在后文中都将词法分析token化的数据文件说成HTML文件。
树是一种数据结构,我们也可以说构建DOM树就是将HTML文件(tokens)中的数据 构造成 树数据结构。
想知道构造DOM树的过程可以去找找树这种数据结构是怎么构造的。
CSSOM树的构造过程同理,不过我们一般把CSS样式作为外链加入到link标签里。浏览器在构建DOM时就会遇到 link 标签,然后向服务器发送请求,接着得到CSS字节文件,经过数据编码Bytes→characters→tokens
→nodes(节点)→object model(对象模型)
这个过程,和DOM构建简直不能太像。
但DOM和SSOM有很多不能忽略的不同之处,我们后面在谈。
DOM和SSOM不是简单的结合就完了,渲染树上的节点是页面能够呈现的内容。
也就是一些HTML 标签和某些样式是不会被呈现出来的,不会被呈现出来就不挂在渲染树上了。比如meta和link标签 就不会当作内容呈现出来,设置了display: none的样式也不会被呈现出来。构建渲染树的主要内容就是匹配DOM和CSSOM上的节点,并捕获可见内容。
渲染树生成后,还是没有办法渲染到屏幕上,渲染到屏幕需要得到各个节点的位置信息,这就需要布局(Layout)的处理了。
布局阶段会从渲染树的根节点开始遍历,由于渲染树的每个节点都是一个Render Object对象,包含宽高,位置,背景色等样式信息。所以浏览器就可以通过这些样式信息来确定每个节点对象在页面上的确切大小和位置。(布局也就是添加 “位置和大小这些信息” 数据的过程)
布局阶段的输出就是我们常说的盒子模型,它会精确地捕获(添加)每个元素在屏幕内的确切位置与大小。
需要注意的是:
float
元素,absoulte
元素,fixed
元素会发生位置偏移。布局完成,开始考虑怎么在屏幕中显示,我们的解决方案是将布局渲染树
浏览器会遍历渲染树,创建一个绘制记录表,该表绘制了顺序。这个阶段称之为绘制阶段。
现在找到了文档的绘制顺序,终于到了该把这些信息转化成像素点显示在屏幕上这一激动人心的时候了。这种行为称之为栅格化。
Chrome最早使用了一种很简单的方式,只删格化用户可视区域的内容,当用户滚动页面时在栅格化更多的内容来填充缺失的部分,这种方式带来的问题显而易见,会导致展示延迟,所以这不断的优化升级。现在的使用了一种更为复杂的栅格化流程,叫做合成(composting)。合成是一种将页面的各个部分分成多个图层,分别对其进行栅格化,并在合成器线程(Compositor Thread)中单独进行合成页面的技术。简单来说就是页面中所有的元素,按照某种规则进行分图层,并把图层都栅格化好了然后只需要把可视区的内容组合成一帧展示给用户即可。
栅格化主线程遍历生成 layer Tree(渲染树),当 layer Tree 生成完毕和布局顺序确定后,主线程将这些信息传递给合成器线程。合成器线程将每个图层栅格化。
主进程中的栅格化前奏——布局+渲染树由于一层可能像页面的整个长度一样大,因此合成器线程将他们切换为许多图块(Tiles)
瓦片然后将每个图块发送给栅格线程(Raster Thread),栅格线程栅格化每个图块,并将它们存储在GPU内存中。当图块栅格化完成后,合成器线程将收集称为"draw quads"的图块信息,这些draw quads信息里记录了图块在内存中的位置和在页面的哪个位置绘制图块的信息。根据这些信息,合成器线程生成了一个合成器帧(Compositor Frame),然后这个合成器帧(Frame)通过IPC传送给浏览器进程,接着浏览器进程将合成器帧传送到GPU,然后GPU渲染展示到屏幕上,这时候恭喜你,你终于看到了页面的内容。
但你的页面发生变化,比如你滚动了当前页面,都会生成一个新的合成器帧,新的合帧再传递给GPU,然后再渲染到屏幕上。
简单点就是调用渲染器(进程)的 paint()
方法在屏幕上显示其内容。渲染树的绘制工作是由浏览器的UI后端组件完成的。
深入浅出浏览器渲染原理 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/53913989浏览器中的进程与线程_大熊猫的五分裤的博客-CSDN博客_浏览器进程和线程https://blog.csdn.net/weixin_44196299/article/details/102651547