I am building an Electron application from Create-React-App and an proxy express server to handle data and backend logic. (Reason for this is I want to separate electron specific api calls with general/other api calls, so I can reuse a lot of the code when this becomes a full web app later on).
My express server is running on localhost:3500, and is running fine when I'm in development mode but when I build the electron app and open the .exe it is loading but no requests being made to the express server. It is however making the electron specific calls as I am getting the version correctly, so I'm guessing I must be missing something when the express server is on a proxy url?
my Electron.js file - lives under project/public/Electron.js
const { ipcMain, app, BrowserWindow, ipcRenderer } = require('electron');
const path = require('path');
const isDev = require('electron-is-dev');
const os = require('os');
const { autoUpdater } = require('electron-updater');
const isElectron = require('is-electron');
const log = require('electron-log');
const server = require('./server/server');
let mainWindow;
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
log.info('App starting...');
log.info('isDev = ', isDev);
log.info('isElectron = ', isElectron());
function createWindow() {
log.info('setting server');
app.server = server;
mainWindow = new BrowserWindow({
width: 1500,
height: 680,
webPreferences: {
nodeIntegration: true,
},
});
mainWindow.loadURL(isDev ? `http://localhost:3000/` : `file://${path.join(__dirname, '../build/index.html')}`);
if (isDev) {
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
mainWindow.webContents.openDevTools();
if (isElectron()) {
//Install Dev Tools using just Electron
BrowserWindow.addDevToolsExtension(
path.join(os.homedir(), '/AppData/Local/Google/Chrome/User Data/Default/Extensions/lmhkpmbekcpmknklioeibfkpmmfibljd/2.17.0_0')
)
BrowserWindow.addDevToolsExtension(
path.join(os.homedir(), '/AppData/Local/Google/Chrome/User Data/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.4.0_0')
)
}
}
mainWindow.on('closed', () => mainWindow = null);
mainWindow.once('ready-to-show', () => {
autoUpdater.checkForUpdatesAndNotify();
});
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
ipcMain.on('catch-on-main', (event, args) => {
//Do stuff
})
ipcMain.on('get-app-version', (event) => {
console.log('appversion=', app.getVersion());
mainWindow.webContents.send('set-app-version', app.getVersion());
});
ipcMain.on('restart-app', () => {
console.log('restarting the app...');
autoUpdater.quitAndInstall();
});
autoUpdater.on('update-available', () => {
console.log('get update is available...');
mainWindow.webContents.send('update-available');
});
autoUpdater.on('download-update', () => {
console.log('get update download...');
mainWindow.webContents.send('download-update');
});
My server file - lives under project/server/server.js
const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const cors = require('cors');
const route = require('./routes/index.js');
const app = express();
const port = process.env.PORT || 3500;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(pino);
app.use(cors());
//app.use('/', baseRoute);
//app.use('/api', returnRoute);
//baseRoute(app);
//returnRoute(app);
app.use('/', route.baseRouter);
app.use('/api/returns', route.returnDetailsRouter);
app.use('/api/users', route.userRouter);
app.use('/api/electron', route.electronRouter);
app.listen(port, () => console.log(`Listening on port ${port}`));
module.exports = app;
My package.json
{
"name": "myelectronapp",
"description": "Electron + Create React App + Electron Builder",
"version": "0.1.0",
"private": true,
"author": {
"name": "myName",
"email": "your.email@domain.com",
"url": "https://your-website.com"
},
"main": "public/electron.js",
"homepage": "./",
"proxy": "http://localhost:3500",
"build": {
"appId": "com.electron-app",
"productName": "electron-app",
"copyright": "Copyright © 2019 ${author}",
"mac": {
"category": "public.app-category.utilities"
},
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
},
"publish": {
"provider": "s3",
"bucket": "bucketName"
}
},
"dependencies": {
"@material-ui/core": "^4.9.4",
"@reduxjs/toolkit": "^1.2.5",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"axios": "^0.19.2",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"electron-is-dev": "^1.1.0",
"electron-log": "^4.0.7",
"electron-updater": "^4.2.4",
"express": "^4.17.1",
"express-pino-logger": "^4.0.0",
"immer": "^5.3.6",
"is-electron": "^2.2.0",
"material-table": "^1.57.2",
"mssql": "^6.1.0",
"mssql-connection-string": "^0.3.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.2.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.0",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"sequelize": "^5.21.5",
"tedious": "^8.0.1"
},
"devDependencies": {
"@rescripts/cli": "^0.0.13",
"@rescripts/rescript-env": "^0.0.11",
"concurrently": "^5.1.0",
"cross-env": "^7.0.0",
"devtron": "^1.4.0",
"electron": "8.0.1",
"electron-builder": "22.4.0",
"electron-rebuild": "^1.10.0",
"electron-reload": "^1.5.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.0.1",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.14.3",
"eslint-plugin-react-hooks": "^1.7.0",
"nodemon": "^2.0.2",
"pino-colada": "^1.5.1",
"wait-on": "^4.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"server": "node ./public/server/server --exec nodemon | pino-colada",
"electron-dev": "concurrently \"cross-env BROWSER=none npm start\" \"wait-on http://localhost:3000 && cross-env NODE_ENV=dev nodemon --exec electron .\"",
"postinstall": "electron-builder",
"preelectron-pack": "npm build",
"electron-pack": "electron-builder build -w --publish never",
"electron-rebuild": "electron-rebuild -p -t \"prod,dev,optional\"",
"electron-deploy": "electron-builder build -w --publish always"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"repository": {
"type": "repoType",
"url": "https://url"
}
}
My build/index.html Tbh, I'm not even sure how this all works and how it loads my react code as there's no mention of the app.js file but it seems to be working~
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="./favicon.ico" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="./logo192.png" />
<link rel="manifest" href="./manifest.json" />
<title>React App</title>
<link href="./static/css/main.de9cbe3d.chunk.css" rel="stylesheet">
</head>
<body><noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script>
! function (e) {
function r(r) {
for (var n, l, p = r[0], a = r[1], f = r[2], c = 0, s = []; c < p.length; c++) l = p[c], Object.prototype
.hasOwnProperty.call(o, l) && o[l] && s.push(o[l][0]), o[l] = 0;
for (n in a) Object.prototype.hasOwnProperty.call(a, n) && (e[n] = a[n]);
for (i && i(r); s.length;) s.shift()();
return u.push.apply(u, f || []), t()
}
function t() {
for (var e, r = 0; r < u.length; r++) {
for (var t = u[r], n = !0, p = 1; p < t.length; p++) {
var a = t[p];
0 !== o[a] && (n = !1)
}
n && (u.splice(r--, 1), e = l(l.s = t[0]))
}
return e
}
var n = {},
o = {
1: 0
},
u = [];
function l(r) {
if (n[r]) return n[r].exports;
var t = n[r] = {
i: r,
l: !1,
exports: {}
};
return e[r].call(t.exports, t, t.exports, l), t.l = !0, t.exports
}
l.m = e, l.c = n, l.d = function (e, r, t) {
l.o(e, r) || Object.defineProperty(e, r, {
enumerable: !0,
get: t
})
}, l.r = function (e) {
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
value: "Module"
}), Object.defineProperty(e, "__esModule", {
value: !0
})
}, l.t = function (e, r) {
if (1 & r && (e = l(e)), 8 & r) return e;
if (4 & r && "object" == typeof e && e && e.__esModule) return e;
var t = Object.create(null);
if (l.r(t), Object.defineProperty(t, "default", {
enumerable: !0,
value: e
}), 2 & r && "string" != typeof e)
for (var n in e) l.d(t, n, function (r) {
return e[r]
}.bind(null, n));
return t
}, l.n = function (e) {
var r = e && e.__esModule ? function () {
return e.default
} : function () {
return e
};
return l.d(r, "a", r), r
}, l.o = function (e, r) {
return Object.prototype.hasOwnProperty.call(e, r)
}, l.p = "./";
var p = this.webpackJsonpmyelectronapp = this.webpackJsonpmyelectronapp || [],
a = p.push.bind(p);
p.push = r, p = p.slice();
for (var f = 0; f < p.length; f++) r(p[f]);
var i = a;
t()
}([])
</script>
<script src="./static/js/2.0f86c59a.chunk.js"></script>
<script src="./static/js/main.44abbb50.chunk.js"></script>
</body>
</html>