I am using 'electron-edge-js' to run a simple C# script in my main.js file. To use the imported package I've set my webpack.main.config.js to:
module.exports = {
entry: ['babel-polyfill','./src/main.js'],
module: {
rules: require('./webpack.rules'),
},
resolve: {
extensions: ['*','.js', '.jsx'],
},
externals: {
'electron-edge-js': 'electron-edge-js',
}
};
This works as expected when using the start script (because the packages are in the node_modules folder). But when the app is packaged, I get the error: module 'electron-edge-js' not found.
When inspecting the built resources>app>node_modules folder I see that it's empty and the created package.json shows no dependencies. I feel like I'm missing something obvious but I've searched and tried possible solutions to no avail.
What does your config.forge data in package.json look like?
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"config": {
"name": "gps_app",
}
},
{
"name": "@electron-forge/maker-zip",
"platforms": [
"darwin"
]
},
{
"name": "@electron-forge/maker-deb",
"config": {}
},
{
"name": "@electron-forge/maker-rpm",
"config": {}
}
],
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.js",
"name": "main_window"
}
]
}
}
]
]
}
},
Minimum test case to reproduce can be found here
or clone: [email protected]:dustinstein/test-app.git
@dustinstein - I'm seeing the same issue here. Did you make any progress on this?
I'm almost embarrassed to say what I did but I was at the end of my expertise. I started a new project with electron-edge-js-quick-start and copied my main electron process code to that project. Since the electron-forge webpack was working well (before packaging or making) I built the project with electron-forge and used the compiled index.js file in .webpack/renderer/main_window folder in my electron-edge-js-quick-start project and it ran and packaged well.
Of course you'll have to manually move dependencies to your package.json and you may have to change Electron versions depending on your project.
When I have time I'm going to dive deeper and see if maybe I can do something a bit cleaner. It works but it's a messy solution.
@dustinstein -
The brute force method might not be elegant - but if it works, it works!
I may end up doing the same if I can't figure out the intended flow for forge + webpack, thanks for the quick response!
Waiting... :)
I have been digging through the packger code for hours and found a solution by adding a few hooks. Basically we need to find out which packages got marked as externals in webpack, and run npm install in the build path to fill up the node_modules folder in the package. Seems hacky but I think it works fine. The inspiration comes from the build steps of serverless-webpack package.
Sharing my forge config here:
const fs = require('fs-extra');
const path = require('path');
const { spawn } = require('child_process');
module.exports = {
packagerConfig: {},
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {
name: 'puppeteer_playground',
},
},
{
name: '@electron-forge/maker-zip',
platforms: [
'darwin',
],
},
{
name: '@electron-forge/maker-deb',
config: {},
},
{
name: '@electron-forge/maker-rpm',
config: {},
},
],
plugins: [
[
'@electron-forge/plugin-webpack',
{
mainConfig: './webpack.main.config.js',
renderer: {
config: './webpack.renderer.config.js',
entryPoints: [
{
html: './src/renderer/index.html',
js: './src/renderer/index.tsx',
name: 'main_window',
},
],
},
},
],
],
hooks: {
readPackageJson: async (forgeConfig, packageJson) => {
// only copy deps if there isn't any
if (Object.keys(packageJson.dependencies).length === 0) {
const originalPackageJson = await fs.readJson(path.resolve(__dirname, 'package.json'));
const webpackConfigJs = require('./webpack.renderer.config.js');
Object.keys(webpackConfigJs.externals).forEach(package => {
packageJson.dependencies[package] = originalPackageJson.dependencies[package];
});
}
return packageJson;
},
packageAfterPrune: async (forgeConfig, buildPath) => {
console.log(buildPath);
return new Promise((resolve, reject) => {
const npmInstall = spawn('npm', ['install'], {
cwd: buildPath,
stdio: 'inherit',
});
npmInstall.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error('process finished with error code ' + code));
}
});
npmInstall.on('error', (error) => {
reject(error);
});
});
}
}
};
@lhr0909 I can't thank you enough. I was stuck in this for two days
@lhr0909 I added your config and it works for the initial compilation step and HMR!
However, any page reload after subsequent webpack rebuilds results in an error:
Unable to load preload script: D:\dev\novocam-recording-software\.webpack\renderer\main_window\preload.js
Error: Cannot find module 'undefinedbuild/Release/video-module.node'
Require stack:
- D:\dev\novocam-recording-software\.webpack\renderer\main_window\preload.js
Even though preload.js is on that path.
Also, running yarn make or yarn package results in
C:\Users\ivanc\AppData\Local\Temp\electron-packager\win32-x64\Futudent-win32-x64\resources\app
An unhandled rejection has occurred inside Forge:
Error: spawn npm ENOENT
at Process.ChildProcess._handle.onexit (node:internal/child_process:282:19)
at onErrorNT (node:internal/child_process:480:16)
at processTicksAndRejections (node:internal/process/task_queues:81:21) {
errno: -4058,
code: 'ENOENT',
syscall: 'spawn npm',
path: 'npm',
spawnargs: [ 'install' ]
}
Electron Forge was terminated. Location:
{}
node:events:355
throw er; // Unhandled 'error' event
^
Error: spawn electron-forge ENOENT
at notFoundError (D:\dev\novocam-recording-software\node_modules\cross-spawn\lib\enoent.js:6:26)
at verifyENOENT (D:\dev\novocam-recording-software\node_modules\cross-spawn\lib\enoent.js:40:16)
at ChildProcess.cp.emit (D:\dev\novocam-recording-software\node_modules\cross-spawn\lib\enoent.js:27:25)
at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
Emitted 'error' event on ChildProcess instance at:
at ChildProcess.cp.emit (D:\dev\novocam-recording-software\node_modules\cross-spawn\lib\enoent.js:30:37)
at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12) {
code: 'ENOENT',
errno: 'ENOENT',
syscall: 'spawn electron-forge',
path: 'electron-forge',
spawnargs: [ 'make' ]
}
error Command failed with exit code 1.
Most helpful comment
I have been digging through the packger code for hours and found a solution by adding a few hooks. Basically we need to find out which packages got marked as externals in webpack, and run
npm installin the build path to fill up thenode_modulesfolder in the package. Seems hacky but I think it works fine. The inspiration comes from the build steps of serverless-webpack package.Sharing my forge config here: