浏览器内核探秘:渲染引擎

427 浏览发布于 作者 zouyang (欢迎转载-请注明出处链接)留下评论分享按钮

一、我们都知道浏览器需要把html和css解析后才能显示在屏幕上,css的解析工作是由浏览器的css引擎完成的。那css引擎都做了什么呢?

css引擎是浏览器渲染引擎中的一个,它负责解析网页文件,并将它们转为像素呈现到屏幕上。
示例图

每一个浏览器都有一个渲染引擎。Chrome的名叫Blink;Edge的名叫EdgeHTML;Safari的名叫Webkit;火狐的名叫Gecko。

为了让浏览器把各种样式文件转换成像素,呈现在屏幕上,所有的浏览器基本上都依次完成了以下步骤:
1、解析出DOM树
将网页文件(html、css)变为浏览器能够识别的对象,html转化为DOM节点树,然后结合css样式文件来确定显示出来的网页样子。浏览器解析完DOM后,便知道这个网页的结构,清楚各个元素之间的层级关系,但是此时还不知道这些元素应该显示成什么样子(样式)。

2、根据样式规则list,为每个DOM节点确定css样式
搞明白各个元素应该显示成什么样子。css引擎会对每一个DOM节点进行一一检查,匹配该节点我们所定义的那些的css规则及属性(如有没定义的属性,自动补全默认css规则属性)。这样每个节点的样子就确定了。
PS:浏览器自己在添加默认css属性值时,是怎么知道该选取哪个属性值呢?
此时浏览器css引擎会用到一种规则数据表,用来排序声明的属性的优先级,优先级最高的,浏览器就会采用该属性值。

3、确定每个DOM节点的大小和在屏幕上的位置
每一个显示的元素都被放入到一个盒子(盒模型)内。

4、绘制(渲染)
引擎会根据各个元素所处的布局层来画出各个元素的图像,就像我们在纸上画图一样。

5、将绘制好的图像拼合在一起,如同我们日常中把很多图片粘贴到一张白纸上。

二、那浏览器是如何渲染图像到我们的屏幕上的呢?
为了说明这个问题,我们将以上5个步骤直接分成2大步骤:

第一步:构建起一个渲染树(有点类似于DOM树),通过设备信息(比如,viewport大小等等)并结合html、css,构建出每一个元素应该长成什么样子(它的宽、高、颜色等等)的渲染树;
第二步:影像合成与渲染,将第一步的渲染树转换成像素显示在屏幕上。

在第二步中,浏览器并不是只渲染这一次,它不得不一次又一次的重复渲染这一页网页,因为任何时间在这个页面上发生的任何变化(例如,一个div的toggle,一个div宽度的变换等等,甚至我们滚动页面),都会引发浏览器重复所有的渲染步骤。

你也许听说过FPS(frames per second)。它跟一本飞速翻阅的图书一样,我们可以用手指来快速的翻书,让书上的连续的静态图像变得好像动起来了。所以,为了让我们翻书动画看起来很流畅,我们需要每秒钟翻书60页。我们把屏幕当成我们的一张书页,书页上排列着无数小的小正方形,也就是我们所说的屏幕上的像素点,每一个像素点可以包含一种颜色。

渲染器的工作就是把每一个像素点都填充上颜色,当整个一页上所有的像素点都填充满了颜色,那么就完成了一次渲染。

电脑上有一个存储缓冲区块叫作帧缓冲地址(frame buffer),它上面的每一个地址坐标存储着RGBA(红, 绿, 蓝, 透明度) 的值,每一个坐标对应屏幕上的每一个像素点。
渲染器将会根据frame buffer上的每一个坐标,渲染RGBA颜色值到每一个像素点上:

当浏览器页面需要刷新的时候,浏览器又会重新看一下frame buffer。

假如我们想要滚动页面或者动画效果看起来很流畅,它们需要有每秒钟60帧,才能看起来流畅。

大多数的电脑每秒钟都会刷新60次,这就是为什么浏览器试着每秒钟渲染60次。这就意味着浏览器有16.67毫秒的时间来完成一次渲染(之前所讲的5步渲染步骤),2次渲染开始时间之间的有16.67毫秒间隔,一般称作帧距(frame budget)。这也解释了jQuery内部执行动画为何要13毫秒执行一次,得至少保证每秒60次渲染,2.0.3版源码如下:

你可能听说过掉帧,掉帧就是系统没能在16.67毫秒内完成那一次的渲染工作,浏览器又从新的frame buffer内拿数据开始下一帧的渲染了。掉帧会让显示效果看起来卡顿。所以我们想要确保在渲染下一帧之前,上一帧的所有像素点都被填充(渲染)完毕了。

那为了能够让每一帧在16.67毫秒内都完成渲染,我们需要让渲染速度变得更快

在最早的浏览器里,也有许多优化措施来加快渲染速度,比如 当我们滚动页面时,检查哪些是变化的内容,只重新渲染那部分就OK了。
随着时间的推移,浏览器开始运用更多的“脏技术”(invalidation techniques),比如“脏矩形”(画面的刷新只更新需要更新的那一块矩形区域)。使用脏矩形技术,可以发现屏幕上最小的变化矩形区域,从而只更新那一区域。

当然,仅靠脏矩形带来的性能提升还不能满足需求,这时,新的技术又出现了,图层和影像合成。图层和影像合成主要用于解决页面大区域更新时的性能问题(图层可以理解成photoshop的图层)。基本上,绘制都在图层上进行,然后再拼合成一整页网页。更新时,只更新那些修改过的图层,以此来提高渲染性能。关于图层和图像拼合,里面有很多细节,比如图层的序列,更新序列的方式,半透明元素的图层叠加渲染,GPU渲染加速等等,足够另开一篇长文来介绍了,后边有时间再码一篇吧:)

(完)

想要打赏,请点击这里

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注