量子近距离观察:什么是浏览器引擎?

去年 10 月,Mozilla 宣布了量子项目 - 我们创建下一代浏览器引擎的计划。我们现在正在这个项目上取得进展。事实上,我们在上个月的 Firefox 53 中发布了量子项目的第一部分

但是,我们意识到,对于那些没有构建网页浏览器的人(大多数人都是如此),可能很难理解为什么我们对 Firefox 进行的一些改变是如此重要。毕竟,我们正在做出的许多改变对于用户来说是不可见的。

考虑到这一点,我们将推出一个博客文章系列,以更深入地了解我们在量子项目中所做的事情。我们希望这个系列文章能让您更好地理解 Firefox 的工作原理,以及 Firefox 如何构建一个下一代浏览器引擎,使其能够更好地利用现代计算机硬件。

为了开始这个系列文章,我们认为最好从解释量子改变的最基本的东西开始。

什么是浏览器引擎,它是如何工作的?


如果我们必须从某个地方开始,那么我们就应该从头开始。

网页浏览器是一个软件,它可以加载文件(通常来自远程服务器)并在本地显示它们,允许用户交互。

量子是我们正在 Mozilla 进行的一个项目的代号,旨在对 Firefox 中负责根据远程文件确定向用户显示内容的那一部分进行大规模升级。该部分在行业中的术语是“浏览器引擎”,如果没有它,您只会看到代码,而不是实际的网站。Firefox 的浏览器引擎称为 Gecko。

很容易将浏览器引擎看成一个单独的黑盒子,就像电视一样 - 数据输入,黑盒子会弄清楚如何在屏幕上显示数据。今天的问题是:如何实现?将数据转化为我们看到的网页需要哪些步骤?

构成网页的数据有很多,但主要分为 3 部分

  • 表示网页结构的代码
  • 提供样式的代码:结构的视觉外观
  • 充当浏览器执行操作的脚本的代码:计算、对用户操作做出反应以及修改最初加载的结构和样式

浏览器引擎将结构和样式组合在一起,以便在屏幕上绘制网页,并确定哪些部分是可交互的。

这一切都从结构开始。当浏览器被要求加载网站时,它会获得一个地址。在这个地址上,另一台计算机在被联系时,会将数据发回浏览器。这如何发生的细节本身就是一个单独的文章,但最终浏览器获得了数据。这些数据以 HTML 格式发回,它描述了网页的结构。浏览器如何理解 HTML?

浏览器引擎包含称为解析器的特殊代码片段,可以将数据从一种格式转换为浏览器在内存中保存的另一种格式1。HTML 解析器获取 HTML,类似于

<section>
 <h1 class="main-title">Hello!</h1>
 <img src="http://example.com/image.png">
</section>

并进行解析,理解

好的,有一个部分。部分内部有一个级别为 1 的标题,它本身包含文本:“Hello!”部分内部还有一个图像。我可以在以下位置找到图像数据:http://example.com/image.png

网页的内存中结构称为文档对象模型,或 DOM。与长文本不同,DOM 表示最终网页的元素树:各个元素的属性以及哪些元素位于其他元素内部。

A diagram showing the nesting of HTML elements

除了描述页面的结构之外,HTML 还包含样式和脚本所在的地址。当浏览器找到它们时,它会联系这些地址并加载它们的数据。然后,这些数据会被送入专门处理这些数据格式的其他解析器。如果找到脚本,它们可以在文件解析完成之前修改页面结构和样式。样式格式 CSS 在我们的浏览器引擎中发挥了下一个作用。

使用样式

CSS 是一种编程语言,允许开发人员描述页面上特定元素的外观。CSS 代表“层叠样式表”,因此得名,因为它允许使用多个样式说明集,其中说明可以覆盖之前或更通用的说明(称为层叠)。一些 CSS 可能如下所示

section {
  font-size: 15px;
  color: #333;
  border: 1px solid blue;
}
h1 {
  font-size: 2em;
}
.main-title {
  font-size: 3em; 
}
img {
  width: 100%;
}

CSS 主要分为称为规则的组,规则本身包含两个部分。第一部分是选择器。选择器描述被设置样式的 DOM 元素(记得上面的那些吗?),以及指定要应用于与选择器匹配的元素的样式的声明列表。浏览器引擎包含一个称为样式引擎的子系统,它的作用是获取 CSS 代码并将其应用于由 HTML 解析器创建的 DOM。

例如,在上面的 CSS 中,我们有一个针对选择器“section”的规则,它将匹配 DOM 中任何具有该名称的元素。然后,对 DOM 中的每个元素进行样式注释。最终,DOM 中的每个元素都完成了样式设置,我们称此状态为该元素的计算样式。当多个竞争样式应用于同一个元素时,后出现的或更具体的样式会获胜。将样式表视为一层层的薄描图纸 - 每层都可以覆盖前一层,但也可以让前一层透出来。

一旦浏览器引擎计算出样式,就该使用它了!DOM 和计算出的样式被馈送到布局引擎,该引擎会考虑要绘制到的窗口的大小。布局引擎使用各种算法来获取每个元素并绘制一个框来容纳其内容,并考虑应用于它的所有样式。

布局完成后,就该将页面的蓝图变成您看到的部分了。这个过程被称为绘制,它是所有先前步骤的最终组合。由布局定义的每个框都被绘制出来,充满了来自 DOM 的内容以及来自 CSS 的样式。现在用户看到了页面,它是根据定义它的代码重建的。

以前就是这样发生的!

当用户滚动页面时,我们会重新绘制,以显示之前在窗口外部的页面新部分。但是,事实证明,用户喜欢滚动!浏览器引擎可以相当肯定地认为它会被要求显示超出其最初绘制的窗口(称为视口)的内容。更现代的浏览器利用了这一事实,并且绘制的网页比最初可见的更多。当用户滚动时,他们想要看到的页面部分已经被绘制出来并准备好了。因此,滚动可以更快、更流畅。这种技术是合成技术的基礎,合成技术是减少所需绘制量的一种技术。

此外,有时我们需要重新绘制屏幕的某些部分。也许用户正在观看以每秒 60 帧播放的视频。或者,也许页面上有一个幻灯片或动画列表。浏览器可以检测到页面某些部分将移动或更新,并且不会重新绘制整个页面,而是创建一个图层来保存该内容。页面可以由许多相互叠加的图层组成。图层可以改变位置、滚动、透明度,或者在其他图层后面或前面移动,而无需重新绘制任何内容!非常方便。

有时,脚本或动画会改变元素的样式。当这种情况发生时,样式引擎需要重新计算元素的样式(以及可能需要重新计算页面上许多其他元素的样式),重新计算布局(进行回流),并重新绘制页面。从计算机速度的角度来看,这需要很多时间,但是只要它只偶尔发生,这个过程就不会对用户的体验造成负面影响。

在现代 Web 应用程序中,文档本身的结构经常会被脚本更改。这可能需要整个渲染过程从头开始,包括将 HTML 解析为 DOM、样式计算、回流和绘制。

标准

并非每个浏览器都以相同的方式解释 HTML、CSS 和 JavaScript。效果可能会有所不同:从小的视觉差异一直到偶尔会出现在一个浏览器中可以工作而在另一个浏览器中根本无法工作的网站。如今,在现代网络上,大多数网站似乎都可以在您选择的任何浏览器中工作。浏览器如何实现这种一致性?

网站代码的格式,以及管理代码如何被解释并转换为交互式视觉页面的规则,都是由相互商定的文档(称为标准)定义的。这些文档由由浏览器制造商、Web 开发人员、设计师以及行业中的其他成员组成的委员会开发。他们共同确定在给定特定代码片段时浏览器引擎应表现出的精确行为。有HTML、CSS 和 JavaScript 的标准,以及图像、视频、音频等的数据格式。

为什么这很重要?可以创建一个全新的浏览器引擎,只要确保您的引擎遵循标准,引擎就会以与所有其他浏览器匹配的方式绘制网页,适用于网络上数十亿个网页。这意味着让网站工作的“秘诀”并不是属于任何一个浏览器的秘密。标准允许用户选择满足其需求的浏览器。

摩尔定律不再适用

当恐龙在地球上漫步,人们只拥有台式电脑的时候,人们认为电脑只会变得越来越快、越来越强大,这似乎是一个合理的假设。这个想法基于 摩尔定律,该定律观察到,芯片上元件的密度(以及因此带来的硅芯片小型化/效率)大约每两年翻一番。令人难以置信的是,这种观察结果在 21 世纪初一直有效,有些人甚至认为它在当今研究的前沿领域仍然有效。那么,为什么普通电脑的速度在过去 10 年中似乎已经趋于稳定了呢?

速度并不是顾客购买电脑时考虑的唯一因素。高速电脑可能非常耗电、发热量很高,而且价格昂贵。有时,人们想要一台具有良好续航时间的便携式电脑。有时,他们想要一台可以放在口袋里的小巧触摸屏电脑,配备摄像头,可以整天无需充电!计算领域的进步让这一切成为可能(这真是太棒了!),但代价是牺牲了原始速度。就像高速驾驶汽车既不经济也不安全一样,高速运行电脑也不经济。解决方法是在单个 CPU 芯片中配备多个“电脑”(核心)。现在,智能手机配备 4 个更小、功率更低的核心已经很常见了。

不幸的是,网页浏览器的历史设计某种程度上假设了速度的持续上升趋势。此外,编写能够同时有效使用多个 CPU 核心的代码可能极其复杂。那么,如何在遍布小型电脑的时代打造一个快速、高效的浏览器呢?

我们有一些想法!

在接下来的几个月里,我们将仔细研究即将对 Firefox 进行的一些更改,以及这些更改如何更好地利用现代硬件来提供 更快、更稳定的浏览器,使网站更加出色。

前进!

[1]: 你的大脑可以做一些类似于解析的事情:单词“eight”是由一串字母组成的,但你会将它们在脑海中转换成数字 8,而不是字母 e-i-g-h-t。 返回


19 条评论

  1. IdiotTake2

    Nightly 性能中有一点我不喜欢:活动标签页的滚动 FPS 会受到后台标签页的影响。例如,当我打开一堆书签,它们同时开始加载时。或者当我恢复先前保存的会话,将 browser.sessionstore.restore_on_demand 设置为 false,Nightly 开始同时加载 3 个恢复的标签页,直到所有恢复的标签页都加载完毕。这真的很烦人。

    Quantum 项目能帮助解决这个问题吗?

    2017 年 5 月 9 日 上午 11:05

    1. Potch

      我们称之为 Quantum DOM 的 Quantum 部分正是关于标签页之间的这种干扰!我们正在使用多种方法来优先处理用户输入和前台标签页的活动,同时限制或甚至暂停后台标签页。我们将发布一篇文章,详细介绍这方面的内容。

      2017 年 5 月 10 日 上午 10:05

      1. IdiotTake2

        非常感谢!Quantum DOM 什么时候会在 Nightly 中启用?2017 年?2018 年?2020 年?

        2017 年 5 月 10 日 下午 11:47

        1. Potch

          Quantum DOM 是一个持续进行的项目,但目标是在今年让第一个部分发挥积极作用。

          2017 年 5 月 11 日 上午 10:52

  2. Alex Vincent

    这是一个关于基本原理的非常好的解释……做得很好。我将把它作为书签,供不了解这些组成部分的人使用。

    2017 年 5 月 9 日 下午 5:18

  3. Joshua

    这是一篇很棒的文章,兄弟。除了您导入的 Rust 部分,您能谈谈你们在改进 C++ 代码库方面做了哪些工作吗?那将会很酷。

    2017 年 5 月 10 日 上午 5:36

    1. Potch

      我将在即将发布的文章中讨论 C++ 方面的事情。那里有很多事情在进行!我们有一个名为 Quantum Flow 的通用性能程序,它专注于对现有代码库进行通用改进。网上有一系列很棒的文章,比我所能谈到的内容要深入得多:https://ehsanakhgari.org/tag/quantumflow

      2017 年 5 月 10 日 上午 10:04

  4. Alex

    Quantum 和 Servo 是同一个东西吗?

    2017 年 5 月 10 日 上午 8:21

    1. Potch

      Quantum 和 Servo 是相关的,但不是同一个东西。Servo 是用 Rust 从头开始重新思考(和重写)的浏览器。Servo 非常注重研究,我们希望有一天能使用纯 Servo 代码,但这还需要几年时间。Quantum 致力于简化 Gecko 的现有组件,并整合已准备好的 Servo 部分,以提高速度。这种划分让 Servo 保持其本色,同时也能让我们在此时改进 Gecko。Servo 擅长快速完成工作,而 Gecko 擅长在不必完成工作时不进行任何操作,因此混合后的产品可以超过其各个部分之和!

      2017 年 5 月 10 日 上午 10:00

  5. Michael M.

    脚注已损坏(ID 后面缺少引号)。是的,当然您只是想演示解析器是如何工作的,以及它们是如何被破坏的 ;-)

    2017 年 5 月 11 日 上午 0:52

    1. Potch

      以及未混淆源代码用于调试的价值!:)

      2017 年 5 月 11 日 上午 10:51

  6. Joshua Jacobson

    文章写得很好,图示也很棒。您使用什么工具制作了它们?

    2017 年 5 月 11 日 上午 7:09

    1. Potch

      我在 Sketch 中绘制了它们(在 Google 应用绘制中进行模拟后)。

      2017 年 5 月 11 日 上午 10:49

  7. The Bionic Cyclist

    请支持 AAC 和 DTS 5.1 播放!:)

    我经常使用 Plex,但没有 5.1 音频是必须的。
    做到这一点,Mozilla 就是王者,Mozilla 本身就很棒,但 5.1 音频更好。

    2017 年 5 月 11 日 上午 8:14

  8. Dago

    这是一篇很棒的文章。
    PS。实际上我读得很仔细,发现“CSS 是一种编程语言”——是吗?

    2017 年 5 月 11 日 下午 2:10

    1. bjorn3

      是的,它是一种[声明式编程语言](https://en.wikipedia.org/wiki/Declarative_programming)。

      2017 年 5 月 18 日 上午 6:55

  9. Doug S.

    正如其他人所说,这是一篇关于基础知识的非常好的高级概述,特别是对于刚接触网络的人来说。内容广泛,但简洁易懂。期待该系列的后续文章!

    2017 年 5 月 12 日 下午 6:20

  10. Robert L

    表达和展示得非常好,即使像我这样的“无技术宅”也能欣赏。

    2017 年 5 月 13 日 上午 6:52

  11. Brian

    Quantum 项目是一个很好的新浏览器引擎名称。

    在我们查看页面之前,我们无法知道它们在 Firefox 和 Chrome 中是否显示相同。在我们查看之前,我们应该预期它们同时工作和出错 :-)

    2017 年 5 月 15 日 上午 3:33

本文的评论已关闭。