从URL输入到页面显示,中间发生了什么(下)

93 阅读4分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

上篇文章讲述了用户输入URL后浏览器进行的一系列处理,从浏览器主进程到网络进程,再到渲染进程的过程。这篇文章接着介绍渲染进程如何把接收到的HTML数据展示在屏幕上的。

渲染进程会对HTML数据的渲染处理

构建DOM树

DOM解析器将HTML转换成浏览器可以理解的DOM树。DOM和HTML的内容几乎是一样的,但DOM是保存在内存中,JS可以查询或操作DOM。

DOM解析器在解析的过程中,如果遇到JS脚本,会先执行JS脚本,执行完成后,在继续往下解析。 如果JS脚本是外链的文件,当解析到JS的时候,会先暂停DOM解析,并下载JS文件,下载完成后执行该JS文件,然后再继续往下解析,这就是JS文件为什么会阻塞DOM渲染

样式计算(Recalculate Style)

将CSS文本转成浏览器可以理解的结构styleSheets;样式表中的属性值标准化处理,转化成渲染引擎容易理解的,标准化的计算值,如将black转成#000等;计算DOM树种每个节点的具体样式。

布局阶段

计算DOM树种可见节点的几何位置。创建布局树,只包含可见元素;布局计算,计算布局树节点的坐标位置。

分层(layer)

为具有层叠上下文的节点创建单独的图层,需要剪裁(clip)的地方也会被创建为图层。并生成一棵对应的图层树(LayerTree),浏览器的页面实际上被分成很多的图层,这些图层叠加后合成最终的页面。

剪裁,比如我们指定div的宽高,内容显示的取悦超过给定的区域,就产生了剪裁

图层绘制

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

栅格化(raster)

绘制列表只是记录绘制的顺序和绘制的指令。真正的绘制操作是由渲染引擎中的合成线程完成的。到图层绘制的列表准备好之后,渲染主线程把该绘制列表给合成线程。合成线程将图层划分为图块(tile),合成线程会按照视口附近的图块优先栅格化 ,图块生成位图的过程叫栅格化。渲染进程维护了一个栅格化的线程池,所有图块栅格化都是在线程池内执行的。

栅格化的过程通常使用GPU来加速生成,GPU操作是运行在GPU进程中,如果栅格化操作使用了GPU,最终生成位图的操作实在GPU中完成的。这就涉及了跨进程操作

合成和显示

所有图块被栅格化后,合成线程就生成一个绘制图块的命令(DrawQuad),让后将该命令给浏览器进程。浏览器进程中有个viz组件用来接收DrawQuad命令,让后根据DrawQuad命令,将页面的内容绘制到内存中,最后再显示在屏幕上。

了解渲染的过程,对于页面的性能优化有帮助

重排,更新元素的几何属性,比如改变了元素的宽高,就会触发重新布局,解析之后的一系列阶段。重排需要更新完整的渲染流水线,所以开销也是最大的。

重绘,更新元素的绘制属性,比如改变元素的背景色,直接进入绘制阶段,解析之后的一系列阶段。重绘省去布局和分层阶段,所以执行效率会比重排操作更高效一些

合成,比如使用CSS的transform实现动画效果,直接在非主线程上执行合成动画的操作。合成能大大的提升绘制的效率。

渲染进程的整个流程参考下边的流程图

graph TD
构建DOM树 --> 样式计算 --> 布局 --> 分层 --> 栅格化 --> 合成

👣 希望本文对大家有帮助,我是果缤纷,期待在下篇文章遇到你~