精读 GitHub - servo 浏览器(一)

一、简介

项目地址:github.com/servo/servo

这一期的精读 GitHub 系列是 servo 浏览器,我们将从源码的角度去拆解 servo 浏览器,逐步厘清整个浏览器的工作原理。

servo 是一款实验性质的现代浏览器引擎,采用 Rust 语言编写(其实是为了写 servo 创建了 Rust 这门语言,但 servo 没火,Rust 先火起来了!),servo 目前还没有独立的 App,需要使用 servoshell 来运行网页;servo 不仅展示了 Rust 语言在系统编程中的强大能力,还开创了并行化布局和渲染的全新理念(其中很多已经被 Firefox 吸收),是一个学习浏览器原理与 Rust 语言非常棒的开源项目。

自 2012 年以来,目前已收获 30K+的 star:

二、安装使用

这里我们以 macOS 为例,介绍如何在编译 servo,以及在 servo 上运行一个网页,其他操作系统按照官方 README 步骤操作即可。

macOS 上编译 servo 步骤:

1)下载 servo 源码:

Shell 复制代码
git clone https://github.com/servo/servo

2)安装Xcodebrew

3)安装uv

Shell 复制代码
curl -LsSf https://astral.sh/uv/install.sh | sh

4)安装 rustup

Shell 复制代码
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

5)重启命令行保证安装的工具生效,在 servo 根目录下运行./mach bootstrap安装依赖

6)在 servo 根目录下运行./mach build进行编译:mach 是 servo 的构建和管理工具

编译成功后,可以通过如下命令运行一个网页:

Shell 复制代码
# 运行网页
./mach run https://example.com

# 无头浏览器模式运行:不启动图形界面
./mach run --headless https://example.com

效果如下:

三、架构介绍

3.1 目录结构

./mach run https://baidu.com命令运行为例,来深入理解这些目录之间是如何协同工作的:

1)ports/servoshell 启动程序,调用 components/constellation 创建一个新的 Tab

2)constellation 指挥 components/net 去下载网页

3)下载的 HTML 传给 components/script 解析成 DOM 树

4)components/style 并行计算样式,附着在 DOM 上

5)components/layout 读取 DOM 和样式,计算位置,生成布局树(Layout Tree)

6)最后,结果被送到 components/compositing 显示到屏幕上

3.2 架构图

上图是单内容进程时的架构图,实际上每个 tab 都可以视为一个进程。

关键点:

1) Constellation

核心协调者,可以理解为 tab 管理器,用于管理多个任务管线(Pipeline)

2)多 Pipeline 并行

图中展示了 A 和 B 两个 Script 线程,servo 在设计上支持一个进程内运行多个独立的渲染管线,比如 iframe 可以有自己独立的管线

3)Script 与 Layout 分离

每个 Script 线程都有一个专属的 Layout 线程

从图中可以看出,网页处理主要分为三个阶段:

阶段 核心职责 说明
Script 所有权 DOM 树,执行 JavaScript,处理导航事件等 当需要知道元素位置(如 offsetWidth)时,必须发消息询问 Layout
Layout 快照 DOM 树,计算样式,构建 Box Tree 和 Fragment Tree 最终生成 Display List 并发送给 Compositor
Compositor UI 线程,接收显示列表,转发给 WebRender 进行 GPU 渲染 UI 事件(如点击、滚动)的第一接收者,通常会将事件转发给 Script 处理

3.3 servo 的加速秘籍

servo 在哪些地方变快了,又是怎么做到的呢?

可以总结如下:

四、总结

通过本文,我们对 servo 有了整体的了解,后续,我们将从源码角度逐步拆解各部分。

更多精彩内容在公众号 「非专业程序员Ping」,欢迎订阅交流!

相关推荐
花褪残红青杏小9 小时前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
lichenyang45312 小时前
Docker 学习笔记(一):为什么需要镜像、容器和仓库?
前端
kyriewen12 小时前
别再对着 TypeScript 报错发呆了:我把 10 个最常见的红色波浪线翻译成了人话
前端·javascript·typescript
IT_陈寒12 小时前
SpringBoot自动配置的坑,我的API突然就404了
前端·人工智能·后端
奇奇怪怪的13 小时前
Embedding 模型 10+ 横向评测
前端
陈广亮13 小时前
Monorepo 从 0 到 1 实操指南 2026 版:pnpm catalogs + Turborepo 2.x + changesets 全链路
前端
子兮曰13 小时前
OpenMontage 深度解剖:你的 AI 编程助手,其实是个视频工作室
前端·后端·ai编程
敲代码的鱼13 小时前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
子兮曰13 小时前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust