API 支持
约 866 字大约 3 分钟
2026-05-09
编译流程
Electron 的 lib 目录中存放了一系列 TypeScript 文件,这些文件实现了 Electron 对外暴露的 JavaScript API,例如 app、ipcMain、ipcRenderer 等。
这些 TypeScript 文件不会在运行时交给用户环境动态编译,而是在 Electron 自身构建阶段就会被提前打包成 JavaScript bundle。
可以先把整个流程理解为下面这个过程:
lib/**/*.ts
↓
根据进程类型分组
↓
webpack 打包
↓
生成 browser_init.js / renderer_init.js / sandbox_bundle.js 等文件
↓
js2c.py 转换为 C++ 数据
↓
生成 electron_natives.cc
↓
编译进 Electron 可执行文件
↓
Node.js 启动时通过 NativeModuleLoader 加载这些内置 JS 模块沿着这个顺序,Electron 首先要做的就是将这些 TypeScript API 实现拆成不同的 bundle。编译 TypeScript 文件的工作被定义在 Electron 的编译脚本 BUILD.gn 中,Electron 会为不同运行环境分别定义打包目标。例如:
构建目标 输出文件
electron_browser_bundle -> browser_init.js
electron_renderer_bundle -> renderer_init.js
electron_sandboxed_renderer_bundle -> sandbox_bundle.js
electron_isolated_renderer_bundle -> isolated_bundle.js
electron_node_bundle -> node_init.js
electron_worker_bundle -> worker_init.js
electron_utility_bundle -> utility_init.js
electron_preload_realm_bundle -> preload_realm_bundle.jsbundle 的输入文件并不相同。比如 browser_init.js 会包含主进程需要的 API 实现,而 renderer_init.js 会包含渲染进程侧需要的 API 实现。因此 Electron 不是把所有 API 都打进同一个文件里,而是根据不同进程和不同执行环境生成不同的初始化脚本。
提示
electron_browser_bundle、electron_renderer_bundle 只是 BUILD.gn 里面定义的构建目标
所以,browser_init.js、renderer_init.js 这类文件可以理解成 Electron API 的 "运行时入口脚本"。它们本质上仍然是 JavaScript,只不过这时候还处在构建产物阶段,还没有真正以普通文件的方式参与运行时加载。
随后这些生成出来的 JavaScript 文件会交给 js2c.py 处理。js2c.py 的作用是把 JavaScript 源码转换成 C++ 里的字符串/数组数据,最终生成 electron_natives.cc
const char browser_init_js[] = "function xxx() { ... }";
const char renderer_init_js[] = "function yyy() { ... }";重要
JS 仍然是 JS,只是被塞进了 C++ 文件里,最后编译进 exe。运行时再由 V8 执行这些 JS,JS 调用系统能力时,会通过 Native Binding 进入 C++
这样做的好处是:
- Electron 内置 API 不需要作为普通 JS 文件分发
- 启动时可以直接从可执行文件内部加载
- 不同进程可以加载各自对应的初始化脚本
- Node.js 的 NativeModuleLoader 可以像加载内置模块一样加载 Electron API
注入流程
前面已经提到,Electron 内部的 TypeScript API 会在构建阶段被打包成不同的 JavaScript bundle,并最终通过 js2c.py 转换进 electron_natives.cc,编译进 Electron 可执行文件。
这些 JS 源码被编进 exe 之后,并不会自动执行。它们只是作为 Electron 内置的 JavaScript 源码数据存在于可执行文件中。
为了让 Node.js 能够识别这些 Electron 内置模块,Electron 会通过补丁修改 Node.js 的内置模块加载逻辑。原本 Node.js 启动时会加载自己的内置 JS 源码,例如 fs、path、module 等。Electron 作为 Node.js 的 embedder,会在这个流程中额外加入一批自己的内置 JS 源码。
补丁中的核心变化可以简化理解为:
LoadJavaScriptSource();
+ LoadEmbedderJavaScriptSource();其中:
LoadJavaScriptSource()
加载 Node.js 自己的内置 JS 模块源码
LoadEmbedderJavaScriptSource()
加载 Electron 作为 embedder 注入的 JS 模块源码