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

时间:2018-10-19 18:17:09

标签: node.js electron

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

main.js:

const { fork } = require('child_process');
fork('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

3 个答案:

答案 0 :(得分:1)

我找到了根本问题。 这是GitHub上的相关issuepull request 1pull request 2

我临时解决此问题的步骤是:

  • 克隆node-gyp git仓库
  • 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来自主项目文件夹(我安装了electronic-rebuild)
  • 调用fork,并且设置了电子版本,如下所示:

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

这是一个hack,但它似乎可以工作。希望这个问题能在上游得到解决。

编辑:固定的拉取请求链接(我使用了第二个拉取请求,而不是第一个)

答案 1 :(得分:0)

我通过以下方法解决了同一问题:

  1. 将Electron更新到v6 Beta。版本6具有adding process.versions.electron to get the Electron version in forked processes所需的功能。
  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的检测功能(versioning.js中的get_process_runtime)查看process.versions.electron,以查看该过程是否为电子过程。否则,它假设一个Node进程。
  • 由于在我的版本(Electron)(v5)中未为分叉进程实现process.versions.electron,因此node-pre-gyp假定为Node进程,并返回到node-v70-win32-x64的路径,该路径不存在,因为我用于npm install node-sqlite3的节点版本与分支过程报告给pre-gyp的节点版本不同。我 在我的node-v67-win32-x64目录中有node_modules/sqlite3/lib/binding
  • 因此,尽管电子制造商在electron-v5.0-win32-x64中正确创建了node_modules/sqlite3/lib/binding,但node-pre-gyp将node-v70-win32-x64返回给node-sqlite3,当然找不到该模块。因此,最后的部分是更新到Electron v6,该版本将Electron版本报告给分叉的过程,从而允许节点预gyp检测电子过程并将正确的路径返回给电子生成器创建的二进制文件,在这种情况下,{{1 }}。

答案 2 :(得分:0)

我只花了两美分,因为这些问题可能非常耗时:我还分叉了一个依赖电子应用程序中sqlite3的过程。

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

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

在父母中:

  1. 包含为devDependency: electron-builder
  2. 添加为安装后脚本electron-builder install-app-deps
  3. 如果这是在添加electronic-builder之后立即进行的,请手动运行postinstall。以后它会在npm i
  4. 之后自动运行

这应该注意针对电子重建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')

应该这样做,希望对大家有帮助。