macOS Production Build: Infinite Window Instantiation and System Freeze
- Dominant language
- TypeScript
- Stars
- 7.1k
- Forks
- 641
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 30
Description
### Pre-flight checklist
- [X] I have read the [contribution documentation](https://github.com/electron/forge/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project uses.
- [X] 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**
```javascript
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**
```javascript
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
```javascript
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**
``` javascript
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](https://github.com/alkaest2002/mpa.git)
Go to the electron-forge folder and issue the command
```javascript
npm run make
```
Get the app from the out folder.
Upon opening the app, the issue appears.
### Additional information
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.