跳转到主内容

Node 原生模块

原生Node.js模块由Electron支持,但由于Electron具有与给定Node.js不同的 应用二进制接口 (ABI)(由于使用Chromium的 BoringSL 而不是 OpenSSL 等 差异),您使用的原生 模块需要为Electron重新编译。 否则,当您尝试运行您的应用程序时, 将会遇到以下的错误:

Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).

如何安装原生模块

有多种不同的方法来安装原生模块:

为 Electron 安装并重新编译模块

您可以像其他 Node 项目一样安装模块,然后用 @electron/rebuild 包重建这些模块以适配 Electron 。 这个包可以自动识别当前 Electron 版本,为你的应用自动完成下载 headers、重新编译原生模块等步骤。 如果您正在使用 Electron Forge,这个工具将在开发模式和发布时自动使用。

例如,你可以通过下面的命令来安装独立的 @electron/rebuild 工具并重新编译模块:

npm install --save-dev @electron/rebuild

# 每次你运行完“npm install”后,运行这条命令:
./node_modules/.bin/electron-rebuild

# 如果运行上述命令在 Windows 上遇到了问题,试试这条命令:
.\node_modules\.bin\electron-rebuild.cmd

关于诸如 Electron Packager 等其他工具的使用和集成的更多信息,请参阅该项目的 README。

通过 npm 安装

只要设置一些系统环境变量,你就可以通过 npm 直接安装原生模块。

例如,要安装所有Electron的依赖:

# Electron 的版本。
export npm_config_target=1.2.3
# 你的机器架构
export npm_config_arch=x64
export npm_config_target_arch=x64
# 下载 Electron 的头文件。
export npm_config_disturl=https://electronjs.org/headers
# 告诉 node-pre-gyp 我们是在为 Electron 生成模块。
export npm_config_runtime=electron
# 告诉 node-pre-gyp 从源代码构建模块。
export npm_config_build_from_source=true
# 安装所有依赖,并缓存到 ~/.electron-gyp。
HOME=~/.electron-gyp npm install

为 Electron 手动编译

如果你是一个原生模块的开发人员,想在 Electron 中进行测试, 你可能要手动编译 Electron 模块。 你可以 使用 node-gyp 直接编译:

cd /path-to-module/
HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://electronjs.org/headers
  • HOME=~/.electron-gyp 设置去哪找头文件
  • --target=1.2.3 设置了 Electron 的版本。
  • --dist-url=...设置了 Electron 的 headers 的下载地址。
  • --arch=x64 设置了该模块为适配64位操作系统而编译。

为Electron的自定义编译手动编译

如果是为一个与公共发行版不匹配的Electron自定义版本编译原生Node模块,需要让npm使用你的Electron自定义版本所对应的Node版本。

npm rebuild --nodedir=/path/to/src/out/Default/gen/node_headers

故障排查

如果您安装了本机模块并发现它无法正常工作,则需要检查以下内容:

  • 当有疑问时,请先执行 @electron/rebuild
  • 确保原生模块与Electron应用程序的目标平台和体系结构兼容。
  • 确保在该模块的binding.gypwin_delay_load_hook没有被设置为false
  • 如果升级了 Electron,你通常需要重新编译这些模块。

关于win_delay_load_hook的说明

在Windows上,默认情况下,node-gyp将原生模块与node.dll链接。 然而,在Electron 4.x和更高的版本中,原生模块需要的symbols由electron.exe导出,并且没有node.dll。 为了能在 Windows 上加载原生模块,node-gyp 安装了一个加载原生模块时会触发的延迟加载钩子,会将 node.dll 引用重定向到加载的可执行文件,而不是在库搜索路径内寻找 node.dll(这将什么都找不到)。 因此,在 Electron 4.x 及更高版本,你需要设置 'win_delay_load_hook': 'true' 来加载原生模块。

如果你遇到诸如 Module did not self-register 或者 The specified procedure could not be found 之类的错误,这可能意味着你尝试使用的模块并没有正确包含延迟加载钩子。 如果模块是用 node-gyp 构建的,请确保 binding.gyp 文件里的 win_delay_load_hook 变量设置为 true,并且不会被其他地方覆盖。 如果模块是在其他系统上构建的,你需要确保构建时要在主 .node 文件中安装延迟加载钩子。 你的 link.exe 调用应该看起来像这样:

 link.exe /OUT:"foo.node" "...\node.lib" delayimp.lib /DELAYLOAD:node.exe /DLL
"my_addon.obj" "win_delay_load_hook.obj"

尤其重要的几点:

  • 你链接的是 Electronnode.lib 而不是 Node 的。 如果你链接了错误的 node.lib,在 Electron 中加载该模块时将引发加载时错误。
  • 你要包含 /DELAYLOAD:node.exe 标志。 node.exe 链接如果没有被延迟,就没有机会触发延迟加载钩子,Node 符号也不会被正确解析。
  • win_delay_load_hook.obj 是直接链接到最终 DLL 里的。 如果钩子是在一个依赖的 DLL 里安装的,它就不会在合适的时间触发。

如果你想实现自己的钩子,请参阅 node-gyp 以获取延迟加载钩子的示例。

依赖于 prebuild 的模块

prebuild 提供了一种通过为多个版本的 Node 和 Electron 预先构建二进制文件来发布原生 Node 模块的方法。

如果 prebuild 驱动的模块提供了能在 Electron 里使用的二进制文件,请确保要省略掉 --build-from-sourcenpm_config_build_from_source 环境变量以便充分利用预构建的二进制文件。

依赖于 node-pre-gyp 的模块

node-pre-gyp 工具 提供一种部署原生 Node 预编译二进制模块的方法, 许多流行的模块都是使用它。

有时这些模块能在 Electron 下正常工作,但如果没有针对 Electron 的二进制文件时,你就需要用源代码构建这些文件。 因此,建议为这些模块使用 @electron/rebuild

如果你通过 npm 的方式安装模块,你需要传入 --build-from-sourcenpm,或是设置 npm_config_build_from_source 环境变量。