原生Node.js模塊由Electron支持,但由于Electron具有與給定Node.js不同的 應(yīng)用二進(jìn)制接口 (ABI)(由于使用Chromium的 BoringSL 而不是 OpenSSL 等 差異),您使用的原生 模塊需要為Electron重新編譯。 否則,當(dāng)您嘗試運(yùn)行您的應(yīng)用程序時(shí), 將會(huì)遇到以下的錯(cuò)誤:
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`).
有多種不同的方法來(lái)安裝原生模塊:
您可以像其他 Node 項(xiàng)目一樣安裝模塊,然后用 electron-rebuild
包重建這些模塊以適配 Electron 。 這個(gè)包可以自動(dòng)識(shí)別當(dāng)前 Electron 版本,為你的應(yīng)用自動(dòng)完成下載 headers、重新編譯原生模塊等步驟。 如果您正在使用 Electron Forge,這個(gè)工具將在開(kāi)發(fā)模式和發(fā)布時(shí)自動(dòng)使用。
例如,你可以通過(guò)下面的命令來(lái)安裝獨(dú)立的 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
有關(guān)使用和與其他工具(如 Electron Packager)集成的更多信息,請(qǐng)參閱項(xiàng)目的自述文件。
只要設(shè)置一些系統(tǒng)環(huán)境變量,你就可以通過(guò) ?npm
? 直接安裝原生模塊。
例如,要安裝所有Electron的依賴(lài):
# Electron 的版本。
export npm_config_target=1.2.3
# Electron的目標(biāo)架構(gòu), 可用的架構(gòu)列表請(qǐng)參見(jiàn)
# https://electronjs.org/docs/tutorial/support#supported-platforms
export npm_config_arch=x64
export npm_config_target_arch=x64
# 下載 Electron 的 headers。
export npm_config_disturl=https://electronjs.org/headers
# 告訴 node-pre-gyp 我們是在為 Electron 生成模塊。
export npm_config_runtime=electron
# 告訴 node-pre-gyp 從源代碼構(gòu)建模塊。
export npm_config_build_from_source=true
# 安裝所有依賴(lài),并緩存到 ~/.electron-gyp。
HOME=~/.electron-gyp npm install
如果你是一個(gè)原生模塊的開(kāi)發(fā)人員,想在 Electron 中進(jìn)行測(cè)試, 你可能要手動(dòng)編譯 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
設(shè)置去哪找頭文件--target=1.2.3
設(shè)置了 Electron 的版本。--dist-url=...
設(shè)置了 Electron 的 headers 的下載地址。--arch=x64
設(shè)置了該模塊為適配64位操作系統(tǒng)而編譯。如果是為一個(gè)與公共發(fā)行版不匹配的Electron自定義版本編譯原生Node模塊,需要讓npm
使用你的Electron自定義版本所對(duì)應(yīng)的Node版本。
npm rebuild --nodedir=/path/to/src/out/Default/gen/node_headers
如果您安裝了本機(jī)模塊并發(fā)現(xiàn)它無(wú)法正常工作,則需要檢查以下內(nèi)容:
electron-rebuild
。binding.gyp
中win_delay_load_hook
沒(méi)有被設(shè)置為false
。在Windows上,默認(rèn)情況下,node-gyp
將原生模塊與node.dll
鏈接。 然而,在Electron 4.x和更高的版本中,原生模塊需要的symbols由electron.exe
導(dǎo)出,并且沒(méi)有node.dll
。為了在 Windows 上加載本機(jī)模塊,node-gyp 安裝了一個(gè)延遲加載掛鉤,它在加載本機(jī)模塊時(shí)觸發(fā),并重定向 node.dll 引用以使用加載可執(zhí)行文件,而不是在庫(kù)搜索中查找 node.dll路徑(什么也沒(méi)有)。因此,在 Electron 4.x 及更高版本上,?'win_delay_load_hook': 'true'
? 是加載本機(jī)模塊所必需的。
如果您收到類(lèi)似 Module did not self-register 或 The specified procedure could not be found 之類(lèi)的錯(cuò)誤,則可能意味著您嘗試使用的模塊未正確包含延遲加載掛鉤。如果模塊是使用 node-gyp 構(gòu)建的,請(qǐng)確保 binding.gyp 文件中的 ?win_delay_load_hook
? 變量設(shè)置為 true,并且不會(huì)在任何地方被覆蓋。如果該模塊是使用另一個(gè)系統(tǒng)構(gòu)建的,則需要確保使用安裝在主 .node 文件中的延遲加載掛鉤進(jìn)行構(gòu)建。您的 link.exe 調(diào)用應(yīng)如下所示:
link.exe /OUT:"foo.node" "...\node.lib" delayimp.lib /DELAYLOAD:node.exe /DLL
"my_addon.obj" "win_delay_load_hook.obj"
特別重要的是:
您從 Electron 而不是 Node 鏈接到 node.lib。如果你鏈接到錯(cuò)誤的 node.lib,當(dāng)你在 Electron 中需要模塊時(shí),你會(huì)得到加載時(shí)間錯(cuò)誤。
您包括標(biāo)志 /DELAYLOAD:node.exe。如果 node.exe 鏈接沒(méi)有延遲,則延遲加載掛鉤將沒(méi)有機(jī)會(huì)觸發(fā),節(jié)點(diǎn)符號(hào)也不會(huì)被正確解析。
win_delay_load_hook.obj 直接鏈接到最終的 DLL 中。如果掛鉤設(shè)置在依賴(lài)的 DLL 中,它不會(huì)在正確的時(shí)間觸發(fā)。
如果您要實(shí)現(xiàn)自己的延遲加載掛鉤示例,請(qǐng)參閱 node-gyp。
prebuild 提供了一種方法來(lái)為多個(gè)版本的 Node 和 Electron 發(fā)布帶有預(yù)構(gòu)建二進(jìn)制文件的原生 Node 模塊。
如果預(yù)構(gòu)建模塊提供二進(jìn)制文件供 Electron 使用,請(qǐng)確保省略 --build-from-source 和 npm_config_build_from_source 環(huán)境變量,以充分利用預(yù)構(gòu)建的二進(jìn)制文件。
node-pre-gyp
工具 提供一種部署原生 Node 預(yù)編譯二進(jìn)制模塊的方法, 許多流行的模塊都是使用它。
有時(shí)這些模塊在 Electron 下運(yùn)行良好,但是當(dāng)沒(méi)有可用的 Electron 特定二進(jìn)制文件時(shí),您將需要從源代碼構(gòu)建。因此,建議對(duì)這些模塊使用 electron-rebuild。
如果您按照 npm 方式安裝模塊,則需要將 --build-from-source 傳遞給 npm,或設(shè)置 npm_config_build_from_source 環(huán)境變量。
更多建議: