很多桌面应用为何自带浏览器引擎?从 Electron 到 WebView2 的二十年轮回
Electron 为何给每个应用塞一份 Chromium?WebView2、Tauri 在解决什么问题?IE 时代又告诉我们共享 Runtime 为何曾经是一场灾难。
装一个「设置面板」或「Markdown 编辑器」,安装包却动辄上百 MB——这类体积往往不是因为业务功能本身有多复杂,而是因为应用自带了一整套浏览器运行时。
当然,并不是所有桌面应用都这样。Photoshop、大部分游戏、传统 Win32/Qt 工具通常不会各自打包一份 Chromium。但在跨平台桌面软件里,Electron 及其同类方案已经把「自带引擎」做成了非常普遍的路径:Discord、Slack、VS Code、Obsidian、Notion 桌面版、Teams……你电脑里很可能同时跑着好几份互不共享的 Chromium 副本。
证据不在任务管理器里——那里通常只显示应用名和内存占用,看不出引擎是否重复。更直观的是安装目录:一个极简的 Electron Hello World,空壳应用往往就有 100 MB 以上;成熟产品的安装包更大,其中 Chromium、V8、Node.js 与 Electron 框架本身占了相当大的比例。磁盘上,这几款应用各自携带的浏览器运行时叠加起来,往往比它们各自的 UI 与业务逻辑显眼得多。
这是过去十几年里一类很典型的取舍:开发效率换用户资源。
Electron 的做法是:为了用 HTML/CSS/JS 写界面,把 Chromium + V8 + Node.js 一并打进安装包,并继承 Chromium 的多进程模型——每个窗口通常还有独立的 renderer process。开发者换来的是跨平台 UI 与生态,用户付的账是安装体积、磁盘占用,以及多开应用时的内存压力。
于是一个很自然的问题出现了:
为什么不让系统维护一份 Chromium Runtime,需要嵌网页的应用共用?
其实非常合理。今天的 WebView2 / WKWebView / Android System WebView / Tauri,某种意义上正是在往这个方向走——只是适用范围、取舍和历史包袱各不相同。
核心结论
- 讨论的是一类选择自带引擎的桌面应用(Electron、CEF 等),不是「所有 App」。
- Electron:用磁盘和内存换开发者的确定性与兼容性。
- WebView2 等共享 Runtime:系统维护一份自动更新的 Web 引擎,应用只带业务代码。
- 引擎单一化(monoculture) 与 Runtime 共享 是两回事——前者危险,后者合理。
哪些应用会自带浏览器引擎?
大致可以分成几类:
| 类型 | 典型例子 | 是否自带完整引擎 |
|---|---|---|
| Electron 应用 | VS Code、Discord、Slack、Obsidian | 是,各带一份 Chromium |
| CEF 嵌入 | Spotify 桌面版、部分游戏启动器 | 是,各带一份 Chromium |
| 系统 WebView | 微信 PC 版部分界面、Tauri 应用 | 否,链接系统 WebView |
| 原生 UI | Office、Adobe、大部分游戏 | 否 |
所以问题不是「每个 App 都有一个浏览器」,而是:当越来越多工具选择 Web 技术栈做桌面 UI 时,重复打包浏览器运行时成了常态。
Electron 为什么偏偏要自带一份 Chromium?
因为它买到了一样开发者非常喜欢的东西:确定性。
Electron 开发者可以认为:
我的 App
├─ Chromium 128
├─ V8 x.x
├─ Node x.x
└─ 我的网页代码然后 Windows、macOS、Linux 上基本都是同一套环境。
不会出现:
用户 A:系统 WebView 太老
用户 B:CSS Grid 行为不一样
用户 C:系统升级后 WebView 更新,App 突然坏了
用户 D:公司电脑锁死了 5 年前版本这其实和游戏打包 runtime 很像。你开发 Unity 游戏通常也不会说:「让用户电脑自己提供一个版本不确定的 Mono/CoreCLR 吧。」因为那会把兼容性问题转嫁给应用。
Electron 的哲学基本就是:
我宁可多占你 150 MB,也不要让你的系统环境决定我的程序是否能运行。
从开发者成本上看,这是极其划算的。从整个电脑生态看,就显得很浪费:
Discord Chromium A(独立副本)
VS Code Chromium B(独立副本)
Slack Chromium C(独立副本)
Notion Chromium D(独立副本)
Teams Chromium E(独立副本)
Obsidian Chromium F(独立副本)它们的功能差异很大,但底层引擎却是同一类东西的多次复制。即便某个成熟产品(比如 VS Code)本身的扩展、语言服务、内置资源也占了不少空间,重复打包 Chromium 这件事仍然是真实存在的额外成本——不是「业务代码只有几 MB」那么简单,而是每多装一个 Electron 应用,就多一份运行时开销。
「.NET Runtime 模式」:WebView2 真的出现了
微软的 WebView2 Evergreen Runtime 基本就是:
浏览器版的 .NET Runtime。
微软官方甚至明确把 WebView2 Runtime 类比成 .NET / Visual C++ Runtime。Evergreen 模式下,系统维护一份自动更新的 WebView2 Runtime,所有 App 共用;Windows 11 通常直接预装。
于是:
Windows
│
├── Edge / WebView2 Runtime
│ └── Chromium
│
├── App A ──┐
├── App B ──┼──→ WebView2
├── App C ──┤
└── App D ──┘甚至当 Edge 和 WebView2 版本相同时,微软会对二进制做 hard-link,减少磁盘占用;已经加载的相关二进制还可能改善启动和内存表现。
这确实比「每个 Electron 应用各自拖一份 Chromium」优雅很多。
Tauri:接受系统 WebView 的取舍
Tauri 的一个核心设计就是:
我不带浏览器。用操作系统已经有的 WebView。
目前它大致是:
Windows → WebView2 → Chromium
macOS → WKWebView → WebKit
Linux → WebKitGTK → WebKitTauri 官方明确说明 WebView library 不会被打包到最终 executable,而是在运行时动态链接系统 WebView,所以应用会小很多。代价就是不同平台 WebView 的差异重新出现了。
| Electron | Tauri | |
|---|---|---|
| 浏览器引擎 | 自带 Chromium | 使用系统 WebView |
| 安装体积 | 大 | 很小 |
| 跨平台一致性 | 极高 | 较低 |
| 引擎版本可控性 | 极高 | 较低 |
| 系统集成 | 一般 | 更自然 |
| 开发兼容性成本 | 低 | 稍高 |
没有绝对胜负。
Electron 是拿用户的磁盘/内存换开发者时间。
Tauri/WebView 是拿开发者的一部分兼容性成本换用户资源。
那为什么操作系统不从一开始就这么干?
其实干过。
Windows 很早就有:
Internet Explorer
↓
MSHTML / Trident
↓
WebBrowser Control
↓
任何 Win32 程序都可以嵌进去也就是你今天设想的东西。
问题是……那个共享浏览器叫 IE。
于是灾难开始了。
为什么微软坚守 IE 那么多年?
这里有一个很讽刺的历史规律:
微软不是因为 IE 太差而无法抛弃 IE。
恰恰是因为 IE 曾经太成功,所以无法抛弃 IE。
90 年代末 IE 击败 Netscape 后,大量企业内部系统开始写成:
IE only
ActiveX
VBScript
MSHTML 特殊行为
IE Document Mode
IE 专属 DOM银行内部系统、政府办公、ERP、OA、工厂管理、医院系统、公司 Intranet——全都可能依赖某个 IE bug。
于是出现一个可怕的问题:
IE6: 错误行为 X
开发者: // 根据错误行为 X 写了网站
微软: IE7: 我们把 X 修正确了
客户: 「我们公司 17 年历史的 ERP 崩了。」微软自己的 Edge 团队后来也明确总结过这个问题:很多网站依赖 IE 特有行为、旧 document mode 和 X-UA-Compatible;修复标准兼容性问题反而会破坏这些站点。
最终 IE11 甚至需要:
IE11
├─ IE11 Mode
├─ IE10 Mode
├─ IE9 Mode
├─ IE8 Mode
└─ IE7 Compatibility Mode浏览器里面带着浏览器考古遗址。
直到今天 Edge 里都还有 IE Mode:现代网页由 Chromium 渲染,而指定的老企业网页仍然调用 IE11 的 Trident/MSHTML,甚至支持 ActiveX。这足以说明当年的技术债有多恐怖。
微软真正的失误:IE6 成功之后
IE6 大约达到统治地位后,微软对浏览器的投入明显放缓。
而 Firefox、Safari、后来 Chrome 开始快速推动 HTML5、CSS3、更好的 JavaScript、标准 DOM、性能与开发工具。IE 则背着 ActiveX、Trident、企业兼容性、旧 Document Mode、Windows 深度绑定一路跑。
于是前端开发经典体验就变成:
/* Chrome */ 正常
/* Firefox */ 基本正常
/* Safari */ 调一下
/* IE */ ?????????以及传奇般的 if IE6 / if IE7 / if IE8 / if IE9 …。
这种跨浏览器不一致,确实长期消耗了大量开发者心力。这也是后来浏览器厂商非常重视 Interop 项目的原因——微软自己现在也把减少跨浏览器不一致列为核心目标。
微软中间还挣扎过一次:EdgeHTML
很多人会忘记:微软没有直接从 IE 跳到 Chromium Edge,而是:
IE / Trident
↓
2015 Edge / EdgeHTML
↓
2020 Edge / Chromium BlinkEdgeHTML 的想法其实挺理想主义:把 IE 二十年的历史包袱砍掉,做一个现代、独立、符合标准的浏览器引擎。微软当时还专门解释过:他们考虑过 WebKit,但担心整个 Web 变成单一引擎,也认为基于自己已有代码开发新引擎更快。
结果几年以后发现一个现实:维护浏览器引擎实在太贵了。
你要实现 HTML、CSS、JS、DOM、Canvas、WebGL、WebRTC、WebAudio、WebAssembly、Video、Fonts、Accessibility、Sandbox、GPU compositing、Network stack、DevTools、Security……
而 Chrome 市占率越来越高以后,又产生另一个问题:很多网站实际上变成「Chrome 能跑就上线」。EdgeHTML 遇到的网站 bug 越来越多。
于是微软 2018 年宣布换 Chromium,并明确把改善兼容性和简化开发者测试矩阵列为原因。
这是一个非常务实的投降:
我们为什么每年花巨大工程资源
重新实现一遍 Chromium 已经实现的东西?那 Apple 为什么不也直接 Chromium?
因为如果 Chrome、Edge、Opera、Brave、Vivaldi、Safari、Firefox 全都用 Blink,那么实际上:
Web 就不再是开放标准,而会逐渐变成「Chromium 的行为就是标准」。
标准可能写着 A,Chromium 实现 B,结果 95% 用户看到 B。开发者就会写 if (worksInChrome) ship();,最后 B 就事实上成为标准。
这就是所谓 browser engine monoculture(浏览器引擎单一化)。
所以保留 Blink、WebKit、Gecko 三支引擎,从整个 Web 的长期健康来看其实很重要。
Apple 的讽刺之处
Apple 在 iOS 上过去长期要求浏览器使用 WebKit。所以 Safari iOS、Chrome iOS、Firefox iOS、Edge iOS 很多时候其实只是不同 UI 的 Safari engine——这反而是另一种 monoculture。
现在规则正在松动。Apple 当前的 App Review Guidelines 仍原则上要求浏览网页的 App 使用 WebKit,但提供 alternative browser engine entitlement;目前欧盟等特定地区已经允许符合条件的替代引擎。
所以 Apple 的逻辑主要不是「WebKit 是世界上最好的」,而更多是安全控制、功耗、系统集成、JIT 权限、进程隔离、App Store 管理与平台控制权。当然,这也给 Apple 带来了很大的争议。
两种「统一」,不能混为一谈
第一种统一:Runtime 分发——我赞成
Windows → WebView2 Runtime
macOS → WKWebView
Android → Android System WebView需要嵌网页的应用,不必各自塞一份完整的 Chromium。这就是现在的趋势。
第二种统一:只剩一个引擎——很危险
Web = Chromium短期对开发者爽得不得了:只测 Chrome,完事。
长期却可能变成:Google 修改 Chromium → 整个 Web 被迫跟随。没有第二个实现去验证「这个到底是 Web 标准,还是 Chromium 特性?」
因此比较健康的状态反而是:
Web Standards
│
┌────────────────┼────────────────┐
↓ ↓ ↓
Blink WebKit Gecko
│ │ │
Chrome/Edge Safari Firefox然后通过 W3C、WHATWG、Web Platform Tests、Interop 等项目,让三者行为尽可能一致,而不是把三者变成一个。
绕了二十多年,又回到了起点
把上面的线索串起来:
1995 IE / MSHTML
↓
其实已经有系统共享 Web Runtime
↓
但 IE 变成兼容性灾难
2008+ Chrome 出现
2013 Electron
↓
一类应用开始各自打包 Chromium
↓
兼容性极好,体积膨胀
2020+ WebView2
↓
共享 Chromium Runtime
↓
兼容性 + 小体积
Tauri
↓
直接利用系统 WebView对选择 Electron 路线的应用来说,各自携带一份 Chromium 确实是一种工程上的奢侈。
而 「系统提供共享、自动更新的 Web Runtime」,对需要嵌网页、又不想重复打包引擎的场景,是更现代、更优雅的方向。
某种意义上,我们绕了二十多年,又回到了一开始想到的那个设计——只是范围更清楚了:
操作系统维护一个类似 CLR 的现代 Web Runtime;需要渲染网页的那一类应用链接它,其余应用照旧走原生 UI。
区别只是这一次终于学会了:Runtime 必须独立于 OS 快速更新、保持强兼容、自动打安全补丁。
这才是 WebView2 相比当年 IE WebBrowser Control 真正关键的进步。