electron/forge

macOS Production Build: Infinite Window Instantiation and System Freeze

alkaest2002 opened this issue · 0 comments

Pre-flight checklist

  • I have read the contribution documentation for this project.
  • I agree to follow the code of conduct that this project uses.
  • I have searched the issue tracker for a bug that matches the one I want to file, without success.

Electron Forge version

7.4.0

Electron version

32.0.2

Operating system

Mac OS Sonoma 14.6.1 (23G93)

Last known working Electron Forge version

N.a.

Expected behavior

App launches

Actual behavior

I have developed a site using the Hugo static site generator and encapsulated the output from the Hugo build process within an Electron application. The development version of the macOS app functions correctly; however, the production build via electron forge cli exhibits a critical issue. Upon launching the production app, the main window is instantiated repeatedly in an infinite loop.

This loop causes multiple windows to stack in the same position on the screen, resulting in an increasingly darker shadow effect beneath them. The continuous creation of windows ultimately leads to a near-total freeze of the macOS environment. Even attempting to force quit the app is insufficient to stop the loop, necessitating a full system reboot to regain control.

The site built with Hugo is a straightforward static site that doesn't include any complex or advanced functionalities. For styling, the site uses Tailwind CSS as the framework. Additionally, the site leverages HTMX and Alpine.js for minimal JavaScript interactivity.

I solved the issue by using the Mac electron prebuilt binary.

VERSION NOT WORKING

  • electron forge cli
  • public folder generated by static site generator
  • server.js
  • main.js

server.js

const express = require('express');
const path = require('path');

const app = express();
const port = 9000;

app.use(express.static(path.join(__dirname, 'public')));

app.listen(port);

main.js

const {app, BrowserWindow} = require('electron');
const path = require('path');
const { fork } = require('child_process');

const ps = fork(path.resolve(__dirname, "server.js"));

const createWindow = () => {

  const mainWindow = new BrowserWindow({
    width: 750,
    minWidth: 750,
    height: 850,
    minHeight: 850,
    webPreferences: { webSecurity: false }
  });
  
  mainWindow.loadFile(path.resolve(__dirname, "public", "index.html"));
  // mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => createWindow());
app.on('window-all-closed', app.quit());
app.on('quit', ps.kill());

VERSION WORKING

NOTE: I let ChatGpt rewrite the server part using only Node native modules.

  • electron prebuilt binary
  • public folder generated by static site generator
  • server.js
  • main.js
const http = require('http');
const fs = require('fs');
const path = require('path');

const port = 9000;
const publicDir = path.join(__dirname, 'public');

const server = http.createServer((req, res) => {
    let filePath = path.join(publicDir, req.url);

    // Check if the request is for a directory or a non-file resource
    if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
        filePath = path.join(filePath, 'index.html');
    }

    // If the file does not exist, check if it's a non-file resource and serve index.html
    if (!fs.existsSync(filePath)) {
        filePath = path.join(publicDir, 'index.html');
    }

    const extname = String(path.extname(filePath)).toLowerCase();
    const mimeTypes = {
        '.html': 'text/html',
        '.js': 'application/javascript',
        '.css': 'text/css',
        '.json': 'application/json',
        '.png': 'image/png',
        '.jpg': 'image/jpg',
        '.gif': 'image/gif',
        '.svg': 'image/svg+xml',
        '.wav': 'audio/wav',
        '.mp4': 'video/mp4',
        '.woff': 'application/font-woff',
        '.ttf': 'application/font-ttf',
        '.eot': 'application/vnd.ms-fontobject',
        '.otf': 'application/font-otf',
        '.wasm': 'application/wasm',
        '.zip': 'application/zip'
    };

    const contentType = mimeTypes[extname] || 'application/octet-stream';

    fs.readFile(filePath, (error, content) => {
        if (error) {
            if (error.code == 'ENOENT') {
                res.writeHead(404, { 'Content-Type': 'text/html' });
                res.end('404 Not Found', 'utf-8');
            } else {
                res.writeHead(500);
                res.end(`Server Error: ${error.code}`, 'utf-8');
            }
        } else {
            res.writeHead(200, { 'Content-Type': contentType });
            res.end(content, 'utf-8');
        }
    });
});

server.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

main.js

const {app, BrowserWindow} = require('electron');
const path = require('path');
const { fork } = require('child_process');

const ps = fork(path.resolve(__dirname, "server.js"));

const createWindow = () => {

  const mainWindow = new BrowserWindow({
    width: 750,
    minWidth: 750,
    height: 850,
    minHeight: 850,
    webPreferences: { webSecurity: false }
  });
  
  mainWindow.loadFile(path.resolve(__dirname, "public", "index.html"));
  // mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => createWindow());
app.on('window-all-closed', () => app.quit());
app.on('quit', () => ps.kill());

Steps to reproduce

Here is my public repo
https://github.com/alkaest2002/mpa.git

Go to the electron-forge folder and issue the command

npm run make

Get the app from the out folder.

Upon opening the app, the issue appears.

Additional information

No response