本节摘要:Electron 起源于 2013 年 GitHub 为 Atom 编辑器开发的内部项目 Atom Shell,2015 年开源并更名,此后沿着"逐步收紧安全默认值"和"跟进 Chromium、Node 版本"两条主线演化。本节按时间轴梳理关键节点,重点解读 remote 模块废除、contextIsolation 默认开启等破坏性变更背后的动机,帮你建立对框架演进方向的判断力。
最初的故事很务实。GitHub 团队要做 Atom 编辑器,当时的编辑器市场由原生方案统治,跨平台意味着三套代码库。团队里全是 Web 工程师,他们问了一个改变行业的问题:能不能用已经熟练的 HTML、CSS、JavaScript 写出一个真正的桌面编辑器?试验项目取名 Atom Shell,思路是把 Chromium 与 Node.js 装进同一个进程模型里。2015 年,项目正式开源并更名为 Electron——取"原子"之意,暗示它是承载电荷(页面)的原子核。
此后的发展呈两条明线、一条暗线。明线之一是跟进底层:Electron 的版本节奏跟随 Chromium 大版本,每次升级意味着新的 CSS 特性、新的 V8 性能、也意味着新的适配工作。明线之二是工具链成熟:从手工配置打包脚本,到 electron-builder 与 Electron Forge 两套官方/半官方方案并存,工程体验逐年改善。暗线则是安全模型的一步步收紧,这条线最能反映框架的真实思考,值得展开。
早期 Electron 为了开发便利,允许渲染进程直接使用完整的 Node.js API——页面上随手一个 require 就能读写磁盘。这在纯本地开发时很爽,但一旦页面加载了远程内容或渲染了用户输入的 HTML,就等于把系统钥匙插在了门上。三次关键收紧由此展开。
第一次是remote 模块的兴废。remote 让渲染进程能"代理调用"主进程侧的对象,看似方便,实则破坏了进程边界、鼓励了懒散的架构,且自带同步 IPC 的性能陷阱。社区争议多年后,Electron 9 开始废弃,14 版本正式移除,官方转而推荐通过预加载脚本暴露白名单式的受控接口。
第二次是contextIsolation 默认开启。Electron 12 起,上下文隔离从"建议开启"变成默认值:页面 JS 与预加载脚本运行在隔离的 V8 上下文里,只能通过显式桥接通信。旧项目升级时大量报错,社区哀嚎一片,但这一刀切断了"页面脚本污染内部原型链"这条真实攻击路径。
第三次是渲染进程默认进沙箱。Electron 20 起 sandbox 默认为真值,渲染进程里彻底没有 Node 能力,连预加载脚本也被限制在极小的 API 子集内。三次收紧方向一致:把能力从页面手里收回来,集中到主进程,按需、白名单式地放行。
用代码对比一下"旧世界"与"新世界"的写法差异,感受收紧的力度:
// 旧世界(Electron 5 时代):渲染进程里直接用 Node,危险但"方便" // 页面脚本中: const fs = require('fs'); const { remote } = require('electron'); remote.dialog.showMessageBox({ message: '我能弹系统对话框' }); fs.writeFileSync('C:/私有配置.ini', '页面直接写系统文件');
// 新世界(当前默认):能力收口到预加载脚本,白名单暴露 // 预加载脚本中: const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld( 'desktop', // 页面里通过 window.desktop 访问,且只能访问下面这些 { saveConfig: (text) => ipcRenderer.invoke('config:save', text), pickFile: () => ipcRenderer.invoke('dialog:open') } );
两相对照,演进逻辑一目了然:新世界里页面拿到的不再是"任意系统权限",而是两个明确命名、可审计的动作。第四章会把这些开关的完整配置基线逐项过一遍。
Electron 的发布策略值得单独一提:它维护稳定的 major 版本线,每个 major 的支持窗口有限,与 Chromium 的支持周期对齐。实践中的经验法则有三条。第一,不要在项目中期顺手升级 major——上游 Chromium 行为差异(例如滚动、字体渲染、API 废弃)常在渲染层冒出回归,应安排专门的升级分支与回归测试。第二,关注安全公告并及时打补丁——Electron 应用自带浏览器内核,Chromium 的高危漏洞同样适用于你,停更的应用等于裸奔的浏览器。第三,读迁移指南再动手——三次安全收紧式的破坏性变更都写明了迁移路径,硬着头皮编译通过往往埋下更深的坑。
一个真实教训:某团队把一个 Electron 8 的老项目直接跳到新版,编译一次通过,欢天喜地上线,结果远程内容加载模块里依赖的旧路径全部静默失效,功能在用户端才暴露。破坏性变更的可怕之处不在编译报错,而在运行时静默改变行为。升级前把涉及 remote、nodeIntegration、webSecurity 的配置点全部盘一遍,是花小钱省大坑。

历史讲完,下一节回到当下:哪些产品真的适合用这套东西,哪些是典型的错配。