前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >重新认识HTML渲染过程

重新认识HTML渲染过程

作者头像
wade
发布2021-05-08 16:15:27
1.5K0
发布2021-05-08 16:15:27
举报
文章被收录于专栏:coding个人笔记

浏览器从输入地址到显示页面的过程,这是面试特别喜欢问的一道题,也是基础的一个概念。到现在,网上能找到的也都是很老的那一套,早之前我的认知也是那样:

DOM树、CSSOM树、render树、布局、绘制、重排、重绘。

最近在学习李兵老师的浏览器工作原理与实践,才知道现在的渲染过程早已经不是这样了,很多概念都是刚知道。自己总结了一下过程和一些概念。

1、构建DOM树:

第一步构建DOM树都是一样的,DMO是document object module,是保存在内存中的树结构,可以通过js查询或修改其内容。浏览器打印document就是这个DOM树。跟浏览器的elements里面是一样的。

输入内容是HTML文件,通过HTML解析器解析,最终生成DOM树

2、样式计算:

以前都说是CSSOM,也就是css object module,保存在内存中用来操作css的对象,好像源码中没有这个概念,也确实没有这个对象。样式计算的过程分为三步:

第一步是转换成浏览器能够理解的结构(styleSheets):样式的来源有三种,link引入、style标签内、行内样式,第一步就是把这些整合变成样式表,可以通过document.styleSheets查看。

第二步是把属性值进行标准化:我们设置样式为rem、bold、red等,最终会被解析成px、700、rgb(255, 0, 0),这就是属性值标准化。

第三步是计算出DOM树中每个节点的具体样式:css有继承规则和层叠规则。继承规则很简单,我父元素设置了字体20px,子元素如果没有另外加样式就都是20px,浏览器也有默认的,所以我们会有reset.css。层叠规则更简单,css本来也是层叠样式表的缩写,定义了如何合并多个来源的属性值算法,我的理解就是权重。查看样式styles可以看见继承和层叠,还有来源,user agent stylesheet就是浏览器默认提供的默认样式。

样式计算最终输出的是每个 DOM 节点的样式,并被保存在 ComputedStyle 的结构内(computed就是最终结果)。

styles可以查看样式继承和层叠规则,computed是最终的计算结果。

输入内容是css的来源,通过渲染引擎输出styleSheets。

3、布局

以前说的render树是很早的时候,说是16年以前的东西,代码早就重构,现在是LayoutTree,也就是布局树。布局是计算出DOM树中可见元素的几何位置。DOM树有些是不可见的元素,设置了display:none属性的元素、head标签、link标签等,所以显示出页面之前需要额外的构建只包含可见元素的布局树。

执行布局操作的时候,会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫 LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单。

4、分层

页面中有很多复杂的效果,如一些复杂的 3D 变换、页面滚动,或者使用 z-indexing 做 z 轴排序等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树(LayerTree)。并不是布局树的每个节点都包含一个图层,如果一个节点没有对应的层,那么这个节点就从属于父节点的图层。

试了一下,fixed定位和body出现滚动条会出现分层,其他的不知道周末出现,可以通过chrome的layers查看:

输入内容是特点的节点,渲染引擎会把这些节点生成专用的图层,生成图层树。

5、图层绘制

完成图层树的构建之后,渲染引擎会对图层树中的每个图层进行绘制。每一个图层的绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表。在图层绘制阶段,输出的内容就是这些待绘制列表。chrome的Layers可以看绘制列表。还可以看每一步绘制的过程。

输入内容是图层树,通过渲染引擎输出绘制列表。

6、生成图块

绘制列表只是用来记录绘制顺序和绘制指令的列表,而实际上绘制操作是由渲染引擎中的合成线程来完成的。当图层的绘制列表准备好之后,主线程会把该绘制列表提交给合成线程。页面内容可能会很大,可视窗口是固定的,如果一次性绘制所有图层,开销太大,所以合成线程会将图层划分为图块(tile),这些图块的大小通常是 256x256 或者 512x512,然后合成线程会按照视口附近的图块来优先生成位图。

7、栅格化

生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的,栅格化过程都会使用 GPU 来加速生成,使用 GPU 生成位图的过程叫快速栅格化,或者 GPU 栅格化,生成的位图被保存在 GPU 内存中。

8、合成和显示

一旦所有图块都被栅格化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。

9、重排、重绘

改变几何属性会重排,会从布局阶段开始执行,重排一定会重绘,就是改变宽高、位置等。重绘是改变颜色等,布局和分层不会重新执行。使用transform能跳过前面的阶段,直接进入合成阶段。

重新认识了一下渲染的过程,中间应该还是有很多的认知不足,现阶段也只能到这种程度了。

(完)

Coding 个人笔记

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 coding个人笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档