WiseLibs / better-sqlite3

The fastest and simplest library for SQLite3 in Node.js.
MIT License
5.5k stars 394 forks source link

Binaries reported as wrong version inside Electron 31 #1203

Closed clubside closed 4 months ago

clubside commented 4 months ago

Howdy!

Love your library, it's been great to work with.

I have been developing an app originally just in Node that I am incorporating into Electron. If I access better-sqlite3 from a utility file, say, node dbtest.js, everything works fine. Unfortunately the exact same code inside Electron produces this:

Error occurred in handler for 'settings:setDatabaseFolder': Error: The module '\\?\V:\dev\vgpavilion\node_modules\better-sqlite3\build\Release\better_sqlite3.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 127. This version of Node.js requires
NODE_MODULE_VERSION 125. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).
    at process.func [as dlopen] (node:electron/js2c/node_init:2:2559)
    at Module._extensions..node (node:internal/modules/cjs/loader:1470:18)
    at Object.func [as .node] (node:electron/js2c/node_init:2:2559)
    at Module.load (node:internal/modules/cjs/loader:1215:32)
    at Module._load (node:internal/modules/cjs/loader:1031:12)
    at c._load (node:electron/js2c/node_init:2:17025)
    at Module.require (node:internal/modules/cjs/loader:1240:19)
    at require (node:internal/modules/helpers:179:18)
    at bindings (V:\dev\vgpavilion\node_modules\bindings\bindings.js:112:48)
    at new Database (V:\dev\vgpavilion\node_modules\better-sqlite3\lib\database.js:48:64) {
  code: 'ERR_DLOPEN_FAILED'
}

As I mentioned there is no problem executing as Node itself but in case it matters here are my version numbers:

node: 22.3.0 electron: 31.0.0 better-sqlite3: 11.0.0

I'm assuming this is an Electron problem but looking for any solution as I cannot continue development until I get past this.

Thanks for any advice, Chris

P.S. I don't know if it's an extension I have installed or a normal feature but inside VSCode next to each non-internal library I require it shows me a size such as for Electron it shows const { app, BrowserWindow, ipcMain, shell } = require('electron') 267 (gzipped: 209) but I don't get that info on the const Database = require('better-sqlite3') line.

P.P.S. I have tried all the "solutions" mentioned in other issues using electron-rebuild (which is deprecated) and it's replacement module @electron/rebuild both of which install with loads of issues, declare rebuild was successful, yet change nothing.

P.P.P.S. I have created a minimal example based on this previous issue comment: https://github.com/WiseLibs/better-sqlite3/issues/1111#issuecomment-1892652682

{
  "name": "se",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "electron": "^31.0.0"
  },
  "dependencies": {
    "better-sqlite3": "^11.0.0"
  }
}
const { app, dialog } = require('electron')
const Database = require('better-sqlite3')

const createWindow = () => {
    const db = new Database(':memory:');

    const version = db.prepare("select sqlite_version()").pluck().get()

    db.close()

    dialog.showMessageBoxSync({ message: `Using sqlite-version ${version}` })

    app.exit(0)
}

app.whenReady().then(() => {
    createWindow()
})

Mine is not a global Electron install so it's different than the linked issue. Still produces the same error as in my full app.

mceachen commented 4 months ago

If you check the pinned Electron installation help topic, https://github.com/WiseLibs/better-sqlite3/issues/126, there should be tips there, but I'm currently using https://github.com/electron/packager (in concert with https://www.electronforge.io/) to manage the native library rebuilds.

Also: Electron v31 isn't supported yet -- it just came out a day ago, and the new version of v8 deleted previously-working code (hence #1200). Try with Electron v30 until the next release is out.

clubside commented 4 months ago

Thanks so much for the reply!

I removed everything but the 2 sample files, changed the dev dependency to "electron": "^30.0.9", did a npm i then followed this advice from the help topic you linked: https://github.com/WiseLibs/better-sqlite3/issues/126#issuecomment-1688319624

The advice was to use this command to rebuild better-sqlite3: npx electron-rebuild -f -w -t dev better-sqlite3

When I run that command it gives me a green checkmark followed by "Rebuild complete" yet the app produces the same error.

There is a lot of stuff to wade through before the comment I linked and nothing related to a vanilla Electron setup in any of the following comments so I'm looking for direction. I know the issue here is tied to the Node and Electron versions. Since I cannot regress Node because of other projects is there a Electron version that the current release is known to work on using the pre-built binary archives? The latest version I see is Electron 23 which is a major step back unless those are just meant for people not using Electron 30.

Since the rebuild is successful as far as it's concerned one other thing people have mentioned is the gyp which I know nothing about. Is there something I can change/add to binding.gyp to get the rebuild to actually target Node 22 and Electron 30?

neoxpert commented 4 months ago

There are prebuilt binaries of better-sqlite3 11.0.0 available for Electron v30 (module version 123) aswell as Node v22 (module version 127).

There is nothing you can control by modifying the binding.gyp. This is more or less just the common compiler settings for the overall project not related to any Node / Electron version. The actual used API header files etc. are passed on from "the outside" by the respective toolchain (node-gyp, prebuilt, electron-rebuild ..).

When it comes to your project setup, you have to decide whether to use Node or Electron as a runtime, but you cannot implement the application with Electron as a target runtime and Node as a runtime to run tests in, if you do not also take care about loading / rebuilding the fitting binary beforehand.

If your goal is to develop an Electron application and to write tests for it, I would recommend to utilize a library like https://github.com/jprichardson/electron-mocha which allows you to also run tests within the very same Electron runtime your application will be using.

clubside commented 4 months ago

I now understand the separation of Node/Electron for the binaries. My problem remains the fact that the basic better-sqlite3 install does not have the Electron binary so I need to know what to download. As I provided in my original post using just 2 files, package.json and index,js I then do npm i and at that point the app will not run because of the error. Which archive do I download that has the file for Electron 30 Windows x64 that I would then place in the Release folder?

neoxpert commented 4 months ago

That would be this archive better-sqlite3-v11.0.0-electron-v123-win32-x64.tar.gz.

You could then either drop the file in node_modules/better-sqlite3/build/release or store it in a custom location and pass the actual path to the better_sqlite3.node file using the nativeBinding option of the Database constructor.

clubside commented 4 months ago

Awesome, thanks so much! And now I know the process for future builds when new versions of Electron are supported!