NodeJS Electron with express
Two things.
First I'd clarify your pathing setup and usage, more like this:
const publicPath = path.resolve(__dirname, '/views');// point for static assetsapp.use(express.static(publicPath));//view engine setupapp.set('views', path.join(__dirname, '/views/'));app.engine('html', require('ejs').renderFile);app.set('view engine', 'html');
Second, I would wrap all my express code into a single file that is a self-executing function, so it runs once when you require it. Such as my express file which I call my app.js
file:
'use strict';(function () { const express = require('express'); const path = require('path'); const logger = require('morgan'); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const routes = require('./routes.js'); const app = express(); const publicPath = path.resolve(__dirname, '../dist'); const port = 3000; // point for static assets app.use(express.static(publicPath)); //view engine setup app.set('views', path.join(__dirname, '../dist')); app.engine('html', require('ejs').renderFile); app.set('view engine', 'html'); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended:true })); app.use('/', routes); app.use(cookieParser()); const server = app.listen(port, () => console.log(`Express server listening on port ${port}`)); module.exports = app;}());
Then in my main file (which I call main.js
not app.js, in my case), I instantiate the app and the express server as follows:
'use strict';const app = require('electron').app;const Window = require('electron').BrowserWindow; // jshint ignore:lineconst Tray = require('electron').Tray; // jshint ignore:lineconst Menu = require('electron').Menu; // jshint ignore:lineconst fs = require('fs');const server = require('./ServerSide/app');let mainWindow = null;app.on('ready', function () { const path = require('path'); const iconPath = path.resolve(__dirname, './dist/myicon.ico'); const appIcon = new Tray(iconPath); mainWindow = new Window({ width: 1280, height: 1024, autoHideMenuBar: false, useContentSize: true, resizable: true, icon: iconPath // 'node-integration': false // otherwise various client-side things may break }); appIcon.setToolTip('My Cool App'); mainWindow.loadURL('http://localhost:3000/'); // remove this for production var template = [ { label: 'View', submenu: [ { label: 'Reload', accelerator: 'CmdOrCtrl+R', click: function(item, focusedWindow) { if (focusedWindow) { focusedWindow.reload(); } } }, { label: 'Toggle Full Screen', accelerator: (function() { if (process.platform === 'darwin') { return 'Ctrl+Command+F'; } else { return 'F11'; } })(), click: function(item, focusedWindow) { if (focusedWindow) { focusedWindow.setFullScreen(!focusedWindow.isFullScreen()); } } }, { label: 'Toggle Developer Tools', accelerator: (function() { if (process.platform === 'darwin') { return 'Alt+Command+I'; } else { return 'Ctrl+Shift+I'; } })(), click: function(item, focusedWindow) { if (focusedWindow) { focusedWindow.toggleDevTools(); } } } ] } ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); mainWindow.focus();});// shut down all parts to app after windows all closed.app.on('window-all-closed', function () { app.quit();});
Note that I am using this with success on Windows platform, so small tweaks may be needed for any platform specific items listed in this example.