跳转到主要内容

原生 Node 模块

Electron 支持原生 Node.js 模块,但由于 Electron 的应用程序二进制接口 (ABI) 与给定的 Node.js 二进制文件不同(例如,Electron 使用 Chromium 的 BoringSSL 而不是 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 的版本,并处理下载头文件和为您的应用程序重建原生模块的手动步骤。如果您正在使用 Electron Forge,此工具将在开发模式和制作分发包时自动使用。

例如,通过命令行安装独立的 @electron/rebuild 工具,然后使用它重建模块:

npm install --save-dev @electron/rebuild

# Every time you run "npm install", run this:
./node_modules/.bin/electron-rebuild

# If you have trouble on Windows, try:
.\node_modules\.bin\electron-rebuild.cmd

有关更多用法信息以及与其他工具(如 Electron Packager)的集成,请参阅项目的 README。

使用 npm

通过设置几个环境变量,您可以直接使用 npm 安装模块。

例如,为 Electron 安装所有依赖项:

# Electron's version.
export npm_config_target=1.2.3
# The architecture of your machine
export npm_config_arch=x64
export npm_config_target_arch=x64
# Download headers for Electron.
export npm_config_disturl=https://electron.js.cn/headers
# Tell node-pre-gyp that we are building for Electron.
export npm_config_runtime=electron
# Tell node-pre-gyp to build module from source code.
export npm_config_build_from_source=true
# Install all dependencies, and store cache to ~/.electron-gyp.
HOME=~/.electron-gyp npm install

手动为 Electron 构建

如果您是一位开发原生模块并希望针对 Electron 进行测试的开发者,您可能希望手动为 Electron 重建模块。您可以直接使用 node-gyp 为 Electron 进行构建:

cd /path-to-module/
HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://electron.js.cn/headers
  • HOME=~/.electron-gyp 更改查找开发头文件的位置。
  • --target=1.2.3 是 Electron 的版本。
  • --dist-url=... 指定下载头文件的位置。
  • --arch=x64 表示模块是为 64 位系统构建的。

为自定义 Electron 构建手动构建

要针对与公共版本不匹配的自定义 Electron 构建编译原生 Node 模块,请指示 npm 使用您与自定义构建捆绑的 Node 版本。

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

故障排除

如果您安装了原生模块但发现它无法正常工作,您需要检查以下事项:

  • 如有疑问,请先运行 @electron/rebuild
  • 确保原生模块与您的 Electron 应用程序的目标平台和架构兼容。
  • 确保模块的 binding.gyp 文件中未将 win_delay_load_hook 设置为 false
  • 升级 Electron 后,通常需要重建模块。

关于 win_delay_load_hook 的说明

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

如果您遇到类似 Module did not self-registerThe 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"

特别是,重要的是:

  • 您链接的是 *Electron* 的 node.lib,而不是 Node 的。如果您链接了错误的 node.lib,在 Electron 中 require 该模块时将遇到加载时错误。
  • 您包含标志 /DELAYLOAD:node.exe。如果 node.exe 的链接不是延迟的,那么延迟加载钩子将没有机会触发,并且 node 符号将不会被正确解析。
  • win_delay_load_hook.obj 会直接链接到最终的 DLL 中。如果钩子设置在依赖 DLL 中,它将不会在正确的时间触发。

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

依赖 prebuild 的模块

prebuild 提供了一种发布原生 Node 模块的方式,支持为多个 Node 和 Electron 版本提供预编译的二进制文件。

如果 prebuild 驱动的模块为 Electron 提供了二进制文件,请确保省略 --build-from-sourcenpm_config_build_from_source 环境变量,以便充分利用预编译的二进制文件。

依赖 node-pre-gyp 的模块

node-pre-gyp 工具提供了一种部署原生 Node 模块并带有预编译二进制文件的方式,许多流行的模块都在使用它。

有时这些模块在 Electron 下工作得很好,但当没有 Electron 特定的二进制文件可用时,您需要从源代码构建。因此,建议将 @electron/rebuild 用于这些模块。

如果您遵循 npm 的安装模块方式,您需要向 npm 传递 --build-from-source,或者设置 npm_config_build_from_source 环境变量。