在分叉进程中需要 sqlite3 本机模块时,电子崩溃



我正在尝试在带有电子的子进程中使用 sqlite3 模块,但我收到未定义符号的错误。此外,仅当我从 electron 的节点运行程序时,才会发生错误.js但是当我从普通节点运行程序时.js一切正常。我认为问题可能与sqlite3模块的"本机性"有关,我尝试了electron-rebuildnpm --build-from-source,它们没有帮助。

主.js:

const { fork } = require('child_process');
fork('fork');

叉.js:

const sqlite3 = require('sqlite3');

package.json:

{
"name": "bugreproduce_sqlite",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"sqlite3": "^4.0.2"
},
"devDependencies": {
"electron": "^3.0.5"
}
}

输出:

> ./node_modules/electron/dist/electron .
/home/myuser/Programming/javascript/bugreproduce_sqlite/node_modules/electron/dist/electron: symbol lookup error: /home/myuser/Programming/javascript/bugreproduce_sqlite/node_modules/sqlite3/lib/binding/node-v64-linux-x64/node_sqlite3.node: undefined symbol: _ZN2v816FunctionTemplate3NewEPNS_7IsolateEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEENS_5LocalIS4_EENSA_INS_9SignatureEEEiNS_19ConstructorBehaviorENS_14SideEffectTypeE

我找到了根本问题。 这是 GitHub 上的相关问题和拉取请求 1、拉取请求 2。

我暂时解决问题的步骤是:

  • Clone node-pre-gyp git repository
  • checkout到sqlite3想要的版本(目前为0.10.3(
  • 应用来自第二个拉取请求的补丁
  • 通过主项目文件夹中的npm install ../path/to/patched/node-pre-gyp安装此修补的节点预 gyp
  • npm i --build-from-source sqlite3(不确定是否需要此命令(并从主项目文件夹中./node_modules/.bin/electron-rebuild(我安装了电子重建(
  • 使用电子版本集调用fork,如下所示:

    fork('fork', [], { env: { ELECTRON_VERSION: "3.0.5" }});

这是一个黑客,但它似乎有效。希望上游能解决问题。

编辑:修复了拉取请求链接(我使用了第二个拉取请求,而不是第一个(

我通过以下方式解决了同样的问题:

  1. 将电子更新到 v6 测试版。版本 6 具有添加process.versions.electron以在分叉进程中获取 Electron 版本所需的功能。
  2. 使用 electron-builder 的 "install-app-deps" 命令作为安装后脚本。这意味着将"postinstall": "electron-builder install-app-deps"放在package.json中的npm脚本中。

至于为什么会出现这个问题:

  • node-sqlite3 的主模块使用 node-pre-gyp 来确定需要哪个编译的 sqlite 二进制文件。
  • node-pre-gyp 尝试检测进程运行时,以将路径返回到进程/平台的正确二进制文件。
  • node-pre-gyp 的检测功能(get_process_runtime版本控制.js(查看process.versions.electron以查看该过程是否是电子过程。否则,它假定节点进程。
  • 由于process.versions.electron没有在我的分叉进程的 Electron (v5( 版本中实现,node-pre-gyp 假设了一个 Node 进程并返回了一个不存在的node-v70-win32-x64路径,因为我用来npm install node-sqlite3的节点版本与分叉进程报告的节点版本不同节点版本节点pre-gyp。我的node_modules/sqlite3/lib/binding目录中确实node-v67-win32-x64
  • 因此,尽管电子生成器在node_modules/sqlite3/lib/binding年正确地创建了electron-v5.0-win32-x64,但node-pre-gyp返回node-v70-win32-x64给node-sqlite3,当然找不到模块。因此,最后一块是更新到 Electron v6,它将电子版本报告给分叉过程,允许节点预 gyp 检测电子过程并将正确的路径返回到电子生成器创建的二进制文件,在本例中为node_modules/sqlite3/lib/binding/electron-v6.0-win32-x64

只有我的两分钱,因为这些问题可能非常耗时: 我还在从电子应用程序中分叉一个依赖于 sqlite3 的进程。

我的设置和工作方式如下(Electron v8.0.1(:

有两个项目文件夹,"父"和"子"。父级是具有主代码和渲染器代码的电子项目。

在父级中:

  1. 包含为devDependency: electron-builder
  2. 添加为安装后脚本electron-builder install-app-deps
  3. 如果这是在添加电子生成器后立即,请手动运行安装后。将来它会在npm i后自动运行

这应该注意针对电子重建sqlite3。

现在让子进程使用该库。

  1. 子进程开发也依赖于sqlite,所以只需在本地安装它
  2. 我使用 webpack 捆绑了我所有的 js 文件
  3. 为了让 webpack 为后端工作,我添加了
externals: {
sqlite3: 'commonjs sqlite3'
},

(通过这种方式,webpack 不会尝试捆绑在 sqlite3 中,这不适用于本机模块。

回到父级:

I. 假设输出包称为"child.js",将其复制到父文件夹,并将其添加到"electron-builder.json"文件中的files属性中,例如files: ["!*.log", "!doc", ..., "child.js"].像这样,孩子被添加到应用程序根目录的 asar 存档中。不要使用电子生成器的extraFiles/extraResources并尝试像那样分叉孩子,您的孩子不会找到sqlite3。

II. 在应用程序的"main.ts"文件中,将子项启动为

fork(path.resolve(app.getAppPath(), 'child.js')

这应该可以做到,希望对任何人都有帮助。

最新更新