浏览器渲染引擎进化史:从 Trident 到 Blink,一个世纪的 Web 底层技术革命

打开 Chrome DevTools,按下 Performance 面板录制一段页面加载,你会看到一条条精确的"火焰图"——HTML 解析、CSS 计算、布局、分层、绘制、合成,每一步都以毫秒级精度被记录。这套精密的流程不过是最近二十年才逐步建立起来的。回望上世纪 90 年代,网景的 Navigator 需要用完全不同的方式理解一个"网页"。本文将带你从历史纵深出发,重新理解浏览器渲染引擎是怎么一步步从"文本排版器"变为现代"多媒体操作系统"的。

一、混沌时代:HTML 还没有标准(1991–1995)

1.1 Tim Berners-Lee 的第一台"浏览器"(1990)

1990 年,CERN 的 Tim Berners-Lee 用 Objective-C 写了一个叫做 WorldWideWeb(后来改名 Nexus)的程序,它既是第一个网页浏览器,也是第一个网页编辑器。它的渲染方式极其朴素:按顺序读入标签,将 <h1> 用大字号显示,<p> 换行,<a> 画一条下划线——没有任何"布局引擎"的概念。

严格来说,它更接近一个支持超链接的文本编辑器。没有盒模型,没有层叠样式表,JavaScript 更是无从谈起。

1.2 Mosaic:图片改变了游戏规则(1993)

NCSA Mosaic 是第一个在行内直接显示图片(<img> 标签)的浏览器,这让网页从"带链接的文档"变成了"多媒体页面"。但 Mosaic 的渲染有一个致命局限:必须等图片下载完才能确定位置——因为布局需要图片才知道最终高度。

这个"盒模型不完善"的问题直到今天仍然影响着前端开发者的体验——只是我们换了个名字叫 CLS(Cumulative Layout Shift,累积布局偏移)。

1.3 第一次浏览器战争(1994–1998)

Netscape Navigator 迅速占据市场,微软则以 IE 反击。这场战争的遗产至今仍在影响 Web:

Trident(IE 的渲染引擎) 做了几件事奠定了现代 Web 的基础:

  • 第一个支持 <iframe>(1996)
  • 第一个实现 JavaScript(当时的 LiveScript,由微软反向工程为 JScript)
  • 第一个引入 XMLHttpRequest 的原型(1999,被 Outlook Web Access 团队发明,后来成为 Ajax 的基础)

但 Trident 也引入了无数"私有行为"——document.all、ActiveX、条件注释 <!--[if IE]>——这些变成了 Web 标准化进程中最难清除的历史包袱。

二、Web 标准时代:Gecko 与 WebKit 的诞生(1998–2008)

2.1 Mozilla 的开源赌注(1998)

1998 年,Netscape 做出了一个大胆决定:将 Navigator 代码开源,成立 Mozilla 项目。这个项目的核心产物就是 Gecko 渲染引擎。

Gecko 的设计哲学与 Trident 完全不同:

  • 严格遵循 W3C 标准
  • 引入分层渲染架构(Frame → View → Layer)
  • 支持 XUL(XML User Interface Language)构建浏览器自身的界面

Gecko 的代码极其臃肿——开源后的前三年,它几乎无法发布稳定版本。直到 2002 年 Phoenix(后来改名 Firefox 0.8)发布,Gecko 才终于向世界证明:一个开源引擎可以战胜商业巨头。

2.2 KHTML 与 KDE 的小众引擎(2000)

KDE 桌面环境有两个组件对今天的 Web 至关重要:KHTML(渲染引擎)和 KJS(JavaScript 引擎)。

这两个组件原本只为 KDE 的文档浏览器 Konqueror 服务,代码量不大,架构清晰。这吸引了苹果一位工程师的注意——后来他将这两个组件带回了 Apple。

2.3 WebKit = KHTML 的重生(2001)

2001 年,Safari 团队(当时还只是苹果的少数几位工程师)需要一个轻量级的渲染引擎用于 Mac OS X。他们评估了 Gecko(太大、耦合度高)和 KHTML(小、干净、LGPL 许可),最终选择了后者。

苹果的改造堪称典范:

  • 剥离 KDE 依赖(Qt → 抽象层)
  • 重写 CSS 引擎,速度提升 3 倍
  • 引入 WebCore(布局/渲染)和 JavaScriptCore(后来改名 Nitro)
  • 实现智能指针、自动缓存、增量布局(incremental layout)

WebKit 的诞生直接催生了 Safari(2003)和后来的所有 iOS 浏览器(苹果要求 iOS 所有浏览器必须使用 WebKit 引擎)。

2.4 渲染管线的成形期

在这个时代,现代渲染管线的雏形逐步稳定。核心流程如下:

HTML 字节流 → Tokenizer → DOM 树
CSS  字节流 → Tokenizer → CSSOM 树
              ↓
        Render Tree(RenderObject 树)
              ↓
        Layout(Reflow,计算盒模型)
              ↓
        Paint(光栅化,画矢量指令)
              ↓
        Composite(合成层,GPU 推送)

注意,这个时期还没有 分层合成(threaded compositing) 的概念——所有步骤都在主线程完成。页面滚动时要么重新 Reflow,要么完全丢帧。

三、V8 引爆的 JavaScript 革命:引擎分化(2008–2013)

3.1 Google Chrome 与 V8(2008)

2008 年 9 月 Google 发布 Chrome,其最大赌注是新的 JavaScript 引擎 V8。当时所有浏览器引擎(SpiderMonkey、JavaScriptCore、Trident 的 JScript)都采用解释执行或简单字节码 JIT(Just-In-Time 编译)。

V8 的革命性创新:

  • 第一个将 JavaScript 完全编译为原生机器码再执行(放弃了字节码中间层)
  • 使用隐藏类(Hidden Classes / Maps)机制追踪属性的布局
  • 采用内联缓存(Inline Cache)快速访问属性
  • 引入分代垃圾回收(Generational GC)

这就是为什么 Chrome 0.2 在 SunSpider 基准测试中比当时 Firefox 快 10 倍的原因——这不是渐进改进,而是范式转移。

3.2 WebKit2 与多进程架构

Firefox 的老版本(到 Firefox 48 之前)长期使用单进程架构:页面渲染、JavaScript、DOM、插件全部跑在一个进程里。一个页面崩溃,整个浏览器就关闭了。

Chrome 从第一天就采用了多进程架构:

  • Browser 进程:UI、地址栏、书签、网络
  • Renderer 进程(每个标签页一个):解析 HTML、运行 JS、布局
  • NPAPI 插件进程

即使某个页面因为死循环卡住,用户可以优雅地关闭它,其余标签页不受影响。

Safari 在 2014 年才引入类似的 WebKit2 架构,而 Firefox 直到 Electrolysis 项目(Firefox 57+,2017)才完成进程隔离。

3.3 Blink:从 WebKit 到分裂(2013)

2013 年 4 月,Google 宣布从 WebKit 中 fork 出自己的渲染引擎 Blink。原因很简单:

  • Chrome 使用 WebKit 的"多进程沙箱"设计,需要大量修改 WebCore 内部逻辑
  • Opera 原本使用 WebKit,随后也转向 Blink
  • 维护两套不同的架构复杂度已经超过了 fork 的成本

Blink 从 WebKit fork 出来后不久就开始激进地砍功能、重构代码:

  • 移除 CSS -webkit- 前缀的非标准属性
  • 实现新的字体选择和文本排版栈
  • 引入 HTML 解析器的惰性回收

四、现代渲染引擎的架构解剖(2014–至今)

现代浏览器(Blink/WebKit/Gecko)的渲染管线已经有了显著的模块分化。

4.1 分层(Layerization)

现代引擎将页面分成多个层(Layer),每个层独立光栅化。常见的层提升条件:

  • transform / opacity / filter 动画
  • will-change 提示
  • <video>、<canvas>、WebGL 元素
  • 3D transform(translateZ(0))
  • 滚动容器(overflow: scroll)

合成线程(Compositor Thread)可以在不阻塞主线程的情况下处理滚动和动画——这直接催生了 60fps 滚动的流畅体验。

4.2 从光栅化到 GPU 加速绘制

早期渲染引擎使用 CPU + Skia(Blink)、Core Graphics(WebKit)画像素。这有两个瓶颈:

  1. 大画布的内存带宽消耗极高
  2. CSS 滤镜(如 box-shadow blurring)逐像素计算代价太大

现代架构(以 Blink 的 GPU Rasterization 为例):

  • Paint 阶段生成的是矢量绘制指令列表(DisplayItemList、PaintChunks),而非位图
  • Compositor 将矢量指令转换为 VBO(Vertex Buffer Object)和纹理
  • GPU 通过 OpenGL/ES、Metal 或 Vulkan 完成纹理采样、变形、滤镜
  • 浏览器自己维护光栅化瓦片(Tile Rasterization)缓存,按视口分辨率动态选择瓦片精度

4.3 V8 的 TurboFan:JIT 的进化

2017 年 Chrome 59 发布 TurboFan 编译器取代旧的 Crankshaft。核心架构:

Ignition(解释器) → 字节码
        ↓(热代码 TurboFan 路径)
  Profile-Guided Optimization(PGO)
        ↓
寄存器分配器 + 优化编译器(基于 SSA)
        ↓
原生机器码

TurboFan 引入了基于 SSA(Static Single Assignment)的优化管道,支持激进的内联、常量折叠、死代码消除和循环不变代码外提(LICM)。新的 Ignition 解释器则将字节码体积缩减了平均 23%,大幅降低内存占用。

4.4 Site Isolation:安全架构的极致(2019 至今)

Spectre 漏洞(2018)暴露了一个根本性问题:如果两个域名共享同一个 Renderer 进程,恶意页面可以通过侧信道(Side-Channel)读取另一个页面的内存内容。

Chrome 的回应是 Site Isolation:每个 <iframe> 跨站时强制放入独立的 Renderer 进程,使不同源的页面永远无法共享同一地址空间。

代价是内存占用平均增加了 10%–15%(因为每个 Renderer 进程都要维护独立的 Blink 堆、V8 堆)。但安全收益巨大:绝大多数基于进程的侧信道攻击因此被阻断。

五、挑战与未来:Web 能否真正替代原生应用?

5.1 WebAssembly(Wasm):Web 性能的终极杠杆

Wasm 最早于 2017 年在所有主流浏览器中推出。它的关键特性:

  • 二进制格式:解析速度比 JS 快 20–30 倍
  • 确定性语义:非常适合沙箱执行
  • 与 JS 互补:不是要替代 JS,而是用于 CPU 密集任务(物理引擎、图片/视频编解码、AI 推理)

2022–2024 年,Wasm 生态发生了三个关键演进:

  1. WASI(WebAssembly System Interface)让 Wasm 脱离浏览器直接运行于服务端(Cloudflare Workers、Fastly Compute)
  2. WasmGC(Wasm Garbage Collection)提案落地——允许 Wasm 直接管理 GC 对象,为 C#、Kotlin、Java 编译到 Wasm 铺平道路
  3. Wasm Threads / SIMD——真正的高性能并行计算

5.2 Interop 2024–2025:跨浏览器壁垒的解冻

主流浏览器厂商(Apple、Google、Mozilla、Microsoft)Interop 项目逐步实现跨浏览器默认的互操作性标准。截止 2025 年:

  • CSS Nesting 已全平台稳定
  • Container Queries 完成全平台部署
  • dialog 元素与 popover API 无差异可用
  • Subgrid 实现接近 100% 互操作

WebKit 团队罕见地在 2024 年公开表态:只在确有严重安全问题时才延迟特性采用。这与 WebKit 过去"先私有化实现再标准化"的文化形成了鲜明对比。

5.3 View Transitions API:Web 终于擅长做视图动画

过去在 Web 中实现平滑的视图切换(比如图片画廊大图模式)极其痛苦。DOM 突变后由于渲染管线同步,"从旧图到新图"的过渡无法插值。

CSS View Transitions API(2023 Chrome 115+,2024 Safari 18+)首次在浏览器层面提供了这一能力。它的原理:

  • 浏览器截取前后两帧画面
  • 将旧元素与新元素配对
  • 通过 CSS 动画平滑插值形变、透明度、位置

这使得 PWA(渐进式 Web 应用)从"接近原生"走向"体验等价原生"。

六、历史留给我们的思考

从 Tim Berners-Lee 在 NeXT Cube 上写下的第一行代码开始,浏览器走了将近 35 年才成为今天这个形态。有三个历史教训值得每一个工程师记住:

第一,兼容性债务是最重的债务。 IE6 的 CSS 盒模型问题困扰了 Web 开发者近十年。Blink fork 出 WebKit 后花了三年才摆脱 -webkit- 的私有前缀噩梦。今天我们要小心——在 Web 平台引入任何新技术前,都必须先想清楚如何优雅降级。

第二,标准不是"谁的方案好",而是"谁愿意付出最大的政治代价"。 Chrome 通过 Blink 的快速垄断最终推动了标准的收敛,但代价是小众浏览器引擎(EdgeHTML、Presto)被边缘化。Web 从今天的角度看是"Chromium 化的 Web"——这既是效率的胜利,也是多样性的损失。

第三,用户感知永远比基准测试更重要。 V8 在 SunSpider 上跑分第一,但如果白屏时间比 Opera 长两秒,用户不会在意。Core Web Vitals(LCP、FID/INP、CLS)指标的提出,本质是业界终于达成了"技术指标要绑定业务效果"的共识。


如今当你在 Chrome 中打开一个页面,背后有大约 24 亿行 Chromium 源码在为你工作——其中包含 800 万行 Blink 渲染引擎代码、300 万行 V8 引擎代码、以及无数人二十年来的工程选择。你的每一次滚动、点击、手势,都经过从 HTML 解析到 GPU 合成的 10 多个阶段的协同计算。这是人类历史上最复杂的软件协作之一,而它仅仅是为了让你"看到"一个网页。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部