I'm trying to develop an Electron Forge Vite app that uses better-sqlite3
as database. It works fine in development environment but after I build a .deb package to test it outside development (I'm on Ubuntu) I get following error:
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'better-sqlite3'
Require stack:
- /usr/lib/babel-gate/resources/app.asar/.vite/build/main.js
-
at Module._resolveFilename (node:internal/modules/cjs/loader:1232:15)
at s._resolveFilename (node:electron/js2c/browser_init:2:124485)
at Module._load (node:internal/modules/cjs/loader:1058:27)
at c._load (node:electron/js2c/node_init:2:16955)
at Module.require (node:internal/modules/cjs/loader:1318:19)
at require (node:internal/modules/helpers:179:18)
at Object.<anonymous> (/usr/lib/babel-gate/resources/app.asar/.vite/build/main.js:30:61788)
at Module._compile (node:internal/modules/cjs/loader:1484:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1564:10)
at Module.load (node:internal/modules/cjs/loader:1295:32)
My forge.config.js
:
const { FusesPlugin } = require("@electron-forge/plugin-fuses");
const { FuseV1Options, FuseVersion } = require("@electron/fuses");
module.exports = {
packagerConfig: {
asar: true,
executableName: "babel-gate",
},
rebuildConfig: {
buildOnly: true,
force: true,
},
makers: [
{
name: "@electron-forge/maker-squirrel",
config: {},
},
{
name: "@electron-forge/maker-zip",
platforms: ["darwin"],
},
{
name: "@electron-forge/maker-deb",
config: {},
},
{
name: "@electron-forge/maker-rpm",
config: {},
},
],
plugins: [
{
name: "@electron-forge/plugin-auto-unpack-natives",
config: {},
},
{
name: "@electron-forge/plugin-vite",
config: {
// `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.
// If you are familiar with Vite configuration, it will look really familiar.
build: [
{
// `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.
entry: "src/main.js",
config: "vite_configs/vite.main.config.mjs",
target: "main",
},
{
entry: "src/preload.js",
config: "vite_configs/vite.preload.config.mjs",
target: "preload",
},
{
entry: "src/overlay/overlay_preload.js",
config: "vite_configs/vite.overlay_preload.config.mjs",
target: "preload",
},
],
renderer: [
{
name: "main_window",
config: "vite_configs/vite.renderer.config.mjs",
},
],
},
},
// Fuses are used to enable/disable various Electron functionality
// at package time, before code signing the application
new FusesPlugin({
version: FuseVersion.V1,
[FuseV1Options.RunAsNode]: false,
[FuseV1Options.EnableCookieEncryption]: true,
[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
[FuseV1Options.EnableNodeCliInspectArguments]: false,
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
[FuseV1Options.OnlyLoadAppFromAsar]: true,
}),
],
};
My package.json
:
{
"name": "babel-gate",
"productName": "BabelGate",
"version": "1.0.0",
"description": "My Electron application description",
"main": ".vite/build/main.js",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"lint": "echo \"No linting configured\""
},
"keywords": [],
"author": {
"name": "fa1ryJack",
"email": "mymail@gmail.com"
},
"license": "MIT",
"devDependencies": {
"@electron-forge/cli": "^7.8.0",
"@electron-forge/maker-deb": "^7.7.0",
"@electron-forge/maker-rpm": "^7.8.0",
"@electron-forge/maker-squirrel": "^7.7.0",
"@electron-forge/maker-zip": "^7.7.0",
"@electron-forge/plugin-auto-unpack-natives": "^7.8.0",
"@electron-forge/plugin-fuses": "^7.7.0",
"@electron-forge/plugin-vite": "^7.7.0",
"@electron/fuses": "^1.8.0",
"@electron/rebuild": "^3.7.1",
"@rollup/plugin-commonjs": "^28.0.3",
"@vitejs/plugin-vue": "^5.2.1",
"electron": "34.3.0",
"electron-forge-maker-appimage": "^26.0.12",
"vite": "^6.2.2"
},
"dependencies": {
"better-sqlite3": "^11.9.1",
"deepl-node": "^1.17.3",
"dotenv": "^16.4.7",
"electron-squirrel-startup": "^1.0.1",
"p-queue": "^8.1.0",
"tesseract.js": "^6.0.0",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
}
}
In my database.js
I call better-sqlite3
as:
const Database = require("better-sqlite3");
electron-rebuild
asarUnpack
and extraResource
for better-sqlite3
in forge.config.js
like this:packagerConfig: {
asar: true,
executableName: "babel-gate",
extraResource: ["./node_modules/better-sqlite3"],
asarUnpack: ["**/node_modules/better-sqlite3/**"]
}
FuseV1Options.OnlyLoadAppFromAsar
to false
Packaging for x64 on Linux
without producing error.The only solution that worked for me is this comment on GitHub under the issue titled as "Forge make combined with vite is creating an incomplete asar".
I modified my forge.config.js
as recommended.
I already had plugin-auto-unpack-natives
entry in plugins
, so I only had to add this ignore
to packagerConfig
ignore:[ /node_modules\/(?!(better-sqlite3|bindings|file-uri-to-path)\/)/, ],