分享

深入了解超快的CSS引擎: Quantum CSS(Stylo)(上)

 alayavijnana 2017-10-02



或许你听说过 Quantum 项目。 它是对于 Firefox 内部的一个重大改写,以达到让 Firefox 更快运行的目的。我们将实验性的浏览器 Servo 的一部分功能调换出来,并对引擎的其他部分做除了重大的改进。

这个项目好比一架正在飞行的飞机的引擎。我们对适当的地方进行改进,一个一个组件地改进, 当着这些组件准备好的时候,你就能够看到它对 Firefox 的影响。


第一个来自 Servo 的主要组件就是一个全新的CSS 引擎,名为 Quantum CSS (之前称作 Stylo) — 现在在浏览器 Nightly 版本中已经可以用于测试了。你可以进入`about:config` 并设置 `layout.css.servo.enabled` 以确保这个功能可以被使用。

这个新引擎将四个浏览器中最先进的革新技术结合在一起,创造出了这个超级 CSS 引擎。


它充分利用了现代的计算机硬件,使你的计算机的所有核心并行工作。这意味着它比原来快2倍,4倍甚至18倍。

另外, 它结合了现有的其他浏览器的最先进的优化方式。 所以即使它不是并行运行,它依旧是一个非常迅捷的 CSS 引擎。


但是 CSS 引擎是做什么的呢?首先,让我们看看 CSS 引擎是如何融入其他浏览器的。然后我们再来看 Quantum CSS 是如何做到更快的。

CSS 引擎的作用是什么?

CSS 引擎是浏览器渲染引擎的一部分。渲染引擎将网站的 HMTL 和 CSS 文件渲染成屏幕上对应的像素。


每个浏览器都有一个渲染引擎。在 Chrome 中它叫做 Blink,在 Edge 中它叫做 EdgeHTML, 在 Safari 中 它叫做 WebKit,在 Firefox 中它叫做 Gecko。

为了转化这些文件成为像素点,所有的这些渲染引擎都会做这些相同的事情:

解析这些文件成浏览器能够理解的对象,包括 DOM。在这一点上, DOM 知道这个页面的结构。它知道元素之间的父子关系。但是它不知道这些元素该是什么样子。



为了弄清楚这些元素究竟该长什么样,对于每个 DOM 节点,CSS 引擎会计算出要应用哪些 CSS 规则,然后计算出那个 DOM 节点应用的每个 CSS 属性的值。


计算出每个节点的大小以及它在屏幕上的位置。 对要出现在屏幕上的东西创建它们所属的盒子。盒子不仅仅代表 DOM 节点,也会有在 DOM 节点内部的盒子,比如文本行。


绘制这些不同的盒子,绘制可以发生在不同的层上。我觉得这个有点像过去用洋葱皮纸上的手绘动画。这使得浏览器可以只切换一个层而不用在其他层上重新绘制。


把这些不同的绘制的层,应用任何像transform 这样的合成属性,然后把他们变成一张图像。这基本上就像是给这些叠在一起的层拍一张照,这张图像之后就会被渲染到屏幕上。


这意味着当渲染引擎开始计算样式,CSS 引擎有两个东西:

  • DOM 树

  • 一张样式规则的清单


它将遍历每个 DOM 节点,然后计算出对应 DOM 节点的样式。对于这部分,它对当前 DOM 节点的每个 CSS 属性都给予一个值,哪怕样式表没有对这个属性声明一个值。

我觉得这好比某个人去填一张表单。他需要为每个 DOM 节点都填写一张表单,然后表单的每个域都要填上最终的答案。


为了做到这一点,CSS 引擎需要做两件事:

  • 计算出当前节点需要应用哪些规则 ,又叫做【选择器匹配】

  • 为任何空缺的值填补上父元素的值或者是默认值,又叫做【层叠】


选择器匹配

对于这一步, 我们将任何匹配当前 DOM 节点的规则添加到一个列表,因为可以匹配多个规则,对于同个属性也可能会有多次声明。


另外,浏览器本身也会添加一些默认 CSS (称作 user agent style sheets)。那么 CSS 引擎怎么知道要选择哪个值呢?

这时候特异性规则就出场了。CSS 引擎基本上会创建一个试算表。然后它会基于不同列分出不同的声明。


拥有最高特异性的规则将会胜出。所以根据这张表,CSS 引擎会应用上它能应用的值。


其他的, 我们会用到层叠。

层叠(the cascade)

层叠让 CSS 更易于书写和维护。因为层叠,你可以在 body 上设置 `color` 属性,然后你就知道 `p`元素和 `span` 元素以及 `li` 元素都使用那个颜色 (除非你有更多具体的样式覆盖)。

为了做到这点,CSS 引擎会查看样式表单中空的盒子。如果这个属性默认是继承的,那么 CSS 引擎就会向树上查找是否有一个祖先节点有值。如果没有任何祖先节点有这个值,或者这个属性没有继承,那么这个属性就会得到一个默认值。


所以现在这个 DOM 节点所有的样式都已经计算好了。

旁注: 样式结构共享

刚刚那个展现给你们的表单其实是有一些曲解的。CSS 有上百个属性。如果 CSS 引擎保持着每个 DOM 节点的每个属性,那内存早就不够用了。

反而, 引擎实际上干的事情,叫做样式结构共享。他们将有关联的数据(比如字体属性)存到不同的对象上,叫做样式结构。然后,计算出的样式只是通过指针指向具体的样式对象,而不是把所有的属性都放在相同的对象上。对于每种属性,都有一个指针指向拥有对应 DOM 节点样式的值的样式结构。


这样既节省了内存又节省了时间。 拥有相似属性的节点(比如兄弟节点)只是指向他们相同的结构并共享那些属性。同时又因为许多属性都是继承的,所以的祖先节点可以和任何不指定具有自己重写属性的后代节点共享同一个结构。


未完待续……
深入了解超快的CSS引擎:Quantum CSS(Stylo)(下)


关于

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多