Search code examples
node.jstypescriptexpresselectronelectron-forge

electron-forge - express not running in final package


I have an Electron application based on the electron-webpack-typescript boilerplate. This application also includes an Express server. Everything works fine when I use the command yarn start for testing, but when I use the command yarn package to create the final build, the Express server doesn't start. The address where the server should run, localhost:5020, returns "This site can't be reached."

Building is provided by electron-forge:

    "start": "electron-forge start",
    "package": "electron-forge package",

index.ts

import { app, BrowserWindow } from 'electron';
import { io } from 'socket.io-client';

declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
let mainWindow: BrowserWindow;

if (require('electron-squirrel-startup')) {
  app.quit();
}

const createWindow = (): void => {
  mainWindow = new BrowserWindow({
    height: 600,
    width: 800,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: true,
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
    },
  });

  mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
  mainWindow.webContents.openDevTools();
};

app.on('ready', () => {
  createWindow();
  startSocketIO();
  runServer();
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

import { runServer } from './server';

function startSocketIO() {
  const socket = io(process.env.SERVER_URL);

  socket.on('connect', () => {
    console.log('Connected to Socket.io server');
    socket.emit('chat message', 'Test message from Electron');
  });

  socket.on('command', (data) => {
    mainWindow.webContents.send('data', data);
  });

  socket.on('disconnect', () => {
    console.log('Disconnected from Socket.io server');
  });
}

server.ts

import express from 'express';
import http from 'http';
import { Server } from 'socket.io';

import dotenv from 'dotenv';
dotenv.config();

const app = express();
const server = new http.Server(app);
const io = new Server(server);

export function runServer(): void {
  app.get('/', (req, res) => {
    if(req.headers.cmd !== undefined) {
      io.emit('command', {
        created: new Date().toLocaleString('pt-BR').replace(',', ''),
        command: atob(req.headers.cmd as string),
        parameters: atob(req.headers.cmddata as string)
      });
    }
    res.send('SERVER RUNNING!')
  
  });
   
  server.listen(process.env.SERVER_PORT, () => {
    console.log(`Socket.IO server running at http://localhost:${process.env.SERVER_PORT}/`);
  });
}

.env

SERVER_URL=http://localhost:5020
SERVER_PORT=5020

I tried to move all variables from .env directly to the code - no changes I also tried to move some of my dependencies in package.json from dependencies to devDependencies - also no changes

// UPDATE 17.05.2023 [15:33]

I discovered that when I move the code:

  server.listen(process.env.SERVER_PORT, () => {
    console.log(`Socket.IO server running at http://localhost:${process.env.SERVER_PORT}/`);
  });

from server.ts directly to the index.ts, everything works properly! So there must be problem with my server.ts definition or in import in index.ts


Solution

  • SOLUTION FOUND!

    I found that the problem was in the dotenv. For some reason, production build created via electron-forge can't export .env variables. In development mode it's possible. I tried to Google possible way how to do this but unfortunately I didn't found anything.

    So I created my own config.ts file, which looks like this:

    const APP_CONFIG = {
      SERVER_PORT: 5020,
      SERVER_URL_BASE: 'http://localhost',
      SERVER_URL: () => {
        return `${APP_CONFIG.SERVER_URL_BASE}:${APP_CONFIG.SERVER_PORT}`;
      }
    }
    
    export default APP_CONFIG;
    

    and then I am including this file by:

    import APP_CONFIG from '../config'
    .
    .
    .
    .
    .
    .
    server.listen(APP_CONFIG.SERVER_PORT, () => {
      console.log(`Socket.IO server running at ${APP_CONFIG.SERVER_URL()}`);
    });