I am trying to build a win app for manipulating files and folders using electron and vuejs by running npm run electron:build
It creates an app but when i run it gives me following error. im sorry for all these snippets but it was expedient that i provide them since i dont know what exactly is the problem. thanks in advance
Error
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Cannot find module 'C:UsersHPDesktopNewFolderprojectathlete-file-managerdist_electronwin-u..background.js'
at Module._resolveFilename (node:internal/modules/cjs/loader:1232:15)
at s_resolveFilename (node:electron/js2c/browser_init:2:123740)
at node:electron/js2c/browser_init:2:129347
at node:electron/js2c/browser_init:2:129596
at node:electron/js2c/browser_init:2:129600
at BuiltInModule.compileForInternalLoader (node:internal/bootstrap/realm:398:7)
at BuiltInModule.compileForPublicLoader (node:internal/bootstrap/realm:337:10)
at loadBuiltinModule (node:internal/modules/helpers:104:7)
at Module._load (node:internal/modules/cjs/loader:1083:17)
at c_load (node:electron/js2c/node_init:2:16955)
i have my background.js
const { app, BrowserWindow, Menu, globalShortcut } = require('electron');
//const fs = require('fs');
const path = require('path');
const isDev = process.env.NODE_ENV === 'development';
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
// Add error handler
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('Failed to load:', errorCode, errorDescription);
});
mainWindow.webContents.on('console-message', (event, level, message) => {
console.log('Renderer Console:', message);
});
if (isDev) {
setTimeout(() => {
mainWindow.loadURL('https://localhost:3000')
.catch((err) => {
console.error('Failed to load URL:', err);
mainWindow.loadURL('http://localhost:3000')
.catch((err) => console.error('Failed to load HTTP fallback:', err));
});
}, 2000);
} else {
// Fix for production build path
const indexPath = path.join(__dirname, '../index.html');
console.log('Loading index from:', indexPath); // For debugging
mainWindow.loadFile(indexPath)
.catch((err) => {
console.error('Failed to load file:', err);
// Fallback attempt
const fallbackPath = path.join(process.resourcesPath, 'app.asar/dist/index.html');
console.log('Attempting fallback path:', fallbackPath);
mainWindow.loadFile(fallbackPath)
.catch((err) => console.error('Fallback also failed:', err));
});
}
// Optional: Enable DevTools in development
if (isDev) {
mainWindow.webContents.openDevTools();
}
// Create the application menu
const template = [
{
label: 'File',
submenu: [
{ role: 'quit' }
]
},
{
label: 'View',
submenu: [
{
label: 'Analytics',
click: () => mainWindow.webContents.send('show-analytics')
},
{
label: 'Scan History',
click: () => mainWindow.webContents.send('show-history')
},
{ role: 'toggleDevTools' }
]
},
{
label: 'Settings',
submenu: [
{
label: 'Keyboard Shortcuts',
click: () => mainWindow.webContents.send('show-shortcuts')
}
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
// Register global shortcuts
globalShortcut.register('Right', () => {
mainWindow.webContents.send('shortcut', 'same-athlete');
});
globalShortcut.register('Down', () => {
mainWindow.webContents.send('shortcut', 'new-athlete');
});
globalShortcut.register('CommandOrControl+R', () => {
mainWindow.webContents.send('shortcut', 'reset');
});
}
// Add before app.whenReady()
app.commandLine.appendSwitch('ignore-certificate-errors');
app.whenReady().then(createWindow);
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
// Clean up shortcuts when quitting
app.on('will-quit', () => {
globalShortcut.unregisterAll();
});
package.json
{
"name": "athlete-file-manager",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"dev": "npm run serve",
"electron:serve": "vue-cli-service electron:serve",
"generate-certs": "node ssl/create-certificates.js",
"server": "node athlete-file-manager-backend/server.js",
"start": "npm run generate-certs && concurrently "npm run server" "vue-cli-service serve" "wait-on https://localhost:3000 && cross-env NODE_ENV=development electron ."",
"setup": "npm install && npm run generate-certs",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"electron:build": "vue-cli-service electron:build",
"electron:dev": "electron .",
"postinstall": "electron-builder install-app-deps",
"postuninstall": "electron-builder install-app-deps",
"rebuild": "electron-rebuild -f -w yourmodulename",
"clean": "rimraf dist_electron",
"build:clean": "npm run clean && npm run electron:build"
},
"main": "src/background.js",
"dependencies": {
"@vueuse/core": "^11.1.0",
"axios": "^1.7.7",
"core-js": "^3.8.3",
"file-saver": "^2.0.5",
"html5-qrcode": "^2.3.8",
"pinia": "^2.2.4",
"selfsigned": "^2.4.1",
"socket.io-client": "^4.8.0",
"vue": "^3.5.12",
"vue-router": "^4.4.5",
"webpack": "^5.95.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@electron-forge/cli": "^7.5.0",
"@types/electron": "^1.6.12",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-plugin-typescript": "^5.0.8",
"@vue/cli-service": "~5.0.0",
"assert": "^2.1.0",
"buffer": "^6.0.3",
"concurrently": "^9.0.1",
"cross-env": "^7.0.3",
"crypto-browserify": "^3.12.0",
"electron": "^33.0.2",
"electron-builder": "^25.1.8",
"electron-devtools-installer": "^3.1.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.7.1",
"events": "^3.3.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"util": "^0.12.5",
"vue-cli-plugin-electron-builder": "~2.1.1",
"wait-on": "^8.0.1",
"webpack-dev-middleware": "^6.1.3",
"webpack-dev-server": "^4.15.1"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}
vue.config.js
const { defineConfig } = require('@vue/cli-service');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
module.exports = defineConfig({
transpileDependencies: true,
pages: {
index: {
entry: 'src/background.js'
}
},
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser',
Buffer: ['buffer', 'Buffer'],
}),
],
resolve: {
fallback: {
path: require.resolve("path-browserify"),
fs: false,
stream: require.resolve("stream-browserify"),
buffer: require.resolve("buffer/"),
events: require.resolve("events/"),
util: require.resolve("util/"),
assert: require.resolve("assert/"),
crypto: require.resolve("crypto-browserify"),
},
alias: {
process: "process/browser"
}
}
},
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
preload: 'src/electron/preload.js',
mainProcessFile: 'src/background.js',
builderOptions: {
productName: 'Athlete File Manager',
appId: 'com.athlete.filemanager',
directories: {
output: 'dist_electron',
buildResources: 'build'
},
files: [
"dist/**/*",
"src/electron/**/*"
],
win: {
target: ['nsis'],
icon: 'public/favicon.ico' // Make sure this path is correct
},
mac: {
target: ['dmg']
}
}
}
},
devServer: {
https: {
key: fs.readFileSync(path.resolve(__dirname, 'ssl/key.pem')),
cert: fs.readFileSync(path.resolve(__dirname, 'ssl/cert.pem')),
//ca: fs.readFileSync(path.resolve(__dirname, 'ssl/cert.pem'))
},
host: 'localhost',
port: 3000,
proxy: {
'/api': {
target: 'https://localhost:5000',
secure: false, // Allow self-signed certificates
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
},
'/socket.io': {
target: 'https://localhost:5000',
ws: true,
changeOrigin: true,
secure: false, // Allow self-signed certificates
}
},
client: {
webSocketURL: {
hostname: 'localhost',
pathname: '/ws',
password: '',
port: 3000,
protocol: 'ws',
},
overlay: {
errors: true,
warnings: false
}
},
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
},
static: {
directory: path.join(__dirname, 'public')
},
compress: true,
hot: true,
historyApiFallback: true
}
});
here is my project structure
athlete-file-manager/
├── athlete-file-manager-backend/
│ ├── node_modules/
│ ├── package.json
│ ├── package-lock.json
│ └── server.js
├── dist_electron/
├── node_modules/
├── public/
│ ├── favicon.ico
│ └── index.html
├── src/
│ ├── assets/
│ │ ├── logo.png
│ │ └── main.css
│ ├── components/
│ │ ├── BulkEntryDialog.vue
│ │ ├── DataEntry.vue
│ │ ├── ExportDialog.vue
│ │ ├── FileRename.vue
│ │ ├── ScanAnalytics.vue
│ │ ├── ScanHistory.vue
│ │ ├── SearchDialog.vue
│ │ └── SecurityWarning.vue
│ ├── composables/
│ │ └── useCameraIntegration.js
│ ├── electron/
│ │ └── preload.js
│ ├── router/
│ │ └── index.js
│ ├── services/
│ │ ├── apiService.js
│ │ ├── exportService.js
│ │ ├── fileRenameService.js
│ │ ├── fileService.js
│ │ └── websocket.js
│ ├── stores/
│ │ ├── athleteStore.js
│ │ └── fileRenameStore.js
│ ├── views/
│ │ ├── Home.vue
│ │ App.vue
│ ├── axios.js
│ ├── main.js
│ └── polyfills.js
│ └── background.js
├── ssl/
│ ├── cert.pem
│ ├── create-certificates.js
│ └── key.pem
├── .env
├── .eslintrc.js
├── .gitignore
├── babel.config.js
├── jsconfig.json
├── package.json
├── package-lock.json
├── README.md
└── vue.config.js