如工程师般探究复杂性——以 Ladybird 浏览器为例 [译]

要掌握复杂性的精髓,最佳策略往往是拆解后再重建。这正是一群志愿者,在一位前 Safari 开发者的带领下所做的事情。他们从零开始打造了一个成熟的操作系统SerenityOS,和一个网络浏览器Ladybird(这意味着:他们没有复用任何现有模块,比如读取 JPEG 文件的模块)。他们如同真正的工程师一般,出于_乐趣_而投入这项工作。听起来不错,但你可能会怀疑,用这种方式能构建出一个具备所有复杂功能的网络浏览器吗?这正是一个探索工程师如何面对复杂性的故事。

被称为“浏览器引擎”的复杂性

二十年前,你可能会为你的网站手写 HTML,或许会用 PHP 来生成。但今天的网站要复杂得多。例如,Dialogic 最近推出的网站需要大约 700 个 JavaScript 模块,并有大约 19,000 行的代码。然而,更令人震惊的复杂性隐藏在表面之下:仅这个网站就可能依赖于其他 130 万(!)行代码。这还不包括支撑网站运作的浏览器引擎和操作系统——也就是说,实际上完成所有繁重工作的软件。想象一下这些引擎需要完成的任务:解析 HTML 和 CSS,决定各部分如何布局,解码多种图像和视频格式,解析和执行 JavaScript 代码,处理安全连接等等。现代浏览器的开发耗费了数十年的时间和巨大的努力,背后是 Google(Chrome)和 Apple(Safari)等公司的推动。

出于好奇,我亲自试用了 Ladybird 浏览器,想看看它的性能如何。这些爱好者没可能达到大公司的水平,对吧?安装它需要一些技巧,因为他们没有提供 Ladybird 的下载链接——记住,这个项目是为了让爱好者寻找乐趣——所以你需要下载源代码并自行构建。这个过程比听起来简单,不久后,一个荷兰新闻网站就成功加载在我的屏幕上了:

如果你知道要寻找什么,你会立即注意到,这已经不仅仅是个业余项目了,实际上,它比创造者所言更接近于一个真正的浏览器:

  • 网站能够通过 HTTPS 无障碍加载,这意味着背后有大量的加密和网络编程工作。
  • 该网站的外观和功能几乎完美,说明实现了相当多的 CSS,并可能还包括了不少 JavaScript。光是首页就加载了 103 个文件,而浏览器似乎毫无压力地处理了它们全部!
  • 字体显示正常,说明浏览器能够正确读取(WOFF 格式)并渲染字体。能够显示文本,也意味着该浏览器支持 Unicode。
  • 有 JPEG 图像显示,说明他们已经解决了图像解码、调整大小以适应屏幕等一系列问题。
  • 浏览器的外观类似 Safari,包括标签页和检查工具,看起来就像一个原生的 macOS 应用。这意味着,这群人不仅为自己的业余操作系统构建了一个浏览器,实际上还开发了一个完整的 macOS 应用程序及其所需的兼容层(他们称之为“Lagom”),使这个浏览器能在其他操作系统上运行。

你可能会问,为什么不测试你之前提到的那个光鲜亮丽的新 Dialogic 网站呢?嗯……

遇到崩溃了,所以是时候找开发者反馈问题了吗?别急,记得这个项目的初衷是_乐趣_,所以这些开发者可能更愿意投入时间在比这个小问题更有趣的事项上。不过,让我们看看能否自己解决这个问题。首先,尝试用尽可能简单的代码复现同样的问题。错误信息暗示问题与网站使用的_网格布局_有关,这是个已知的复杂点。我最初的猜测是浏览器引擎不支持动态 CSS 计算(使用_calc(…)_),但实际上它处理得很好。在代码中加入一些打印语句后,我最终确定问题出在网站上的另一个网格布局上。这个布局的 CSS 如下:

.four {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(auto-fit, auto);
}

找到问题后,我决定向开发者提交一个问题,询问他们我应该查看哪里来解决这个问题(在开源社区,人们通常喜欢你能提供一个清晰的描述和可重现的测试案例,但如果你能帮忙解决问题,他们会更加欢迎!)。几分钟后,他们就指引我查看 CSS 规范,我发现我的 CSS 实际上是不符合规范的——‘repeat(auto-fit, auto)’中不允许使用‘auto’。如果我之前在 Safari 检查器中检查过,就会发现它也忽略了这一行

。在 Ladybird 中修复这个问题,只需让它也忽略这个无效的 CSS 规则。这就是我所做的,结果如下:

尽管布局还不尽如人意(一些 SVG 图标未显示,页面过宽,还有分词的破折号),浏览器不再崩溃,网站实际上是可用的。我很好奇这个以乐趣为出发点的项目一年后会有怎样的进展。

对我而言,这个故事的启示是:巨大的复杂性并不意味着无法理解,也不代表“拆解再重建”的方法不可行——如果你有足够的动力和技能,就能够独立取得很大的进展,正如这个项目所展示的。老实说,我们并非都能成为这些开发者那样的超级程序员——至少我不是——但这个故事告诉我们,每个人都有可能做出有意义的贡献。如果直接拆解重建对你来说太难,不妨尝试为他人的项目贡献一份力量——这样做非常有成就感,而且的确很有_乐趣_。