6月2日 01:18

Electron 原生模块怎么用?N-API 和 node-gyp 编译实战

Electron 原生模块是用 C/C++ 写的 Node.js 模块,通过 N-API 或 NAN 桥接到 JavaScript。常见于需要调用系统 API(文件系统、硬件、加密)或追求极致性能的场景。难点不在写 C++ 代码,而在编译——Electron 用的 Node.js 版本和系统 Node 可能不同,导致原生模块编译失败。

为什么需要原生模块

JavaScript 做不了的事:调用操作系统的原生 API(注册表、系统通知、硬件接口)、极高性能计算(图像处理、加密)、复用已有的 C/C++ 库。

常见的原生模块:node-serialport(串口通信)、node-gyp(编译工具链)、sharp(图像处理,底层 libvips)、keytar(系统密钥管理)。

原生模块的两种方式

1. N-API(推荐):Node.js 官方提供的稳定 ABI。用 N-API 编译的模块不依赖特定 Node.js 版本,Electron 升级时不需要重新编译。

2. NAN(旧方案):直接用 V8 的 C++ API,不同 Node 版本间 API 会变,每次 Electron 升级可能需要重编译。新项目不要用 NAN。

编译原生模块

Electron 的 Node.js 版本和系统安装的 Node 版本不同,所以原生模块必须针对 Electron 重新编译。

方法一:electron-rebuild(最简单)

bash
npm install electron-rebuild --save-dev npx electron-rebuild

自动检测 Electron 的 Node 版本和 ABI,重新编译所有原生模块。

方法二:prebuild(推荐发布流程)

很多原生模块提供预编译二进制(prebuild),不需要本地编译。但 Electron 需要指定下载对应版本:

bash
npm install --runtime=electron --target=28.0.0 --disturl=https://electronjs.org/headers

--target 是 Electron 版本号,--disturl 指向 Electron 的头文件下载地址。

自己写一个原生模块

用 N-API C++ 写模块,用 node-gyp 编译:

cpp
// src/addon.cpp #include <node_api.h> napi_value Hello(napi_env env, napi_callback_info info) { napi_value result; napi_create_string_utf8(env, "Hello from C++!", NAPI_AUTO_LENGTH, &result); return result; } napi_value Init(napi_env env, napi_value exports) { napi_value fn; napi_create_function(env, "hello", NAPI_AUTO_LENGTH, Hello, NULL, &fn); napi_set_named_property(env, exports, "hello", fn); return exports; } NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
python
# binding.gyp { "targets": [{ "target_name": "addon", "sources": ["src/addon.cpp"] }] }
bash
npm install --build-from-source

在 Electron 里使用:

javascript
const addon = require('./build/Release/addon.node'); console.log(addon.hello()); // "Hello from C++!"

常见编译问题

MODULE_NOT_FOUNDUnsatisfied dependency:原生模块没有针对 Electron 重编译。跑 npx electron-rebuild 解决。

node-gyp 编译报错:缺少构建工具链。macOS 需要 Xcode Command Line Tools(xcode-select --install),Windows 需要 npm install -g windows-build-tools,Linux 需要 build-essentialpython3

Mac M1/M2 芯片兼容:arm64 架构的原生模块需要用 arm64 版的 Electron 编译。如果用 Rosetta 跑 x64 版 Electron,原生模块也要编译成 x64。electron-rebuild 会自动匹配架构。

打包时处理原生模块

用 electron-builder 打包时,原生模块会被自动包含。但如果用了 asar 打包,原生模块不能放在 asar 里面(.node 文件不能从 asar 中加载)。electron-builder 默认会把原生模块解压到 app.asar.unpacked 目录,不需要手动处理。

标签:Electron