feat: add headless mode support for electron

- Add --headless flag to run electron without GUI
- Add startup logging for debugging
- Improve headless mode exit handling (auto-exit after 5s)
- Refactor args variable to argsGlobal for clarity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 15:58:36 +08:00
parent 2f24b0f522
commit 207b56bf69

View File

@@ -4,6 +4,31 @@ import { fileURLToPath } from 'url';
import fs from 'fs';
import http from 'http';
function parseArgs() {
const args = { docs: null, headless: false, port: null };
const docsIndex = process.argv.indexOf('--docs');
if (docsIndex !== -1 && process.argv[docsIndex + 1]) {
args.docs = process.argv[docsIndex + 1];
}
if (process.argv.includes('--headless')) {
args.headless = true;
}
const portIndex = process.argv.indexOf('--port');
if (portIndex !== -1 && process.argv[portIndex + 1]) {
args.port = parseInt(process.argv[portIndex + 1], 10);
}
return args;
}
const argsGlobal = parseArgs();
if (argsGlobal.headless) {
app.commandLine.appendSwitch('disable-gpu');
app.commandLine.appendSwitch('disable-software-rasterizer');
app.commandLine.appendSwitch('no-sandbox');
app.disableHardwareAcceleration();
}
app.commandLine.appendSwitch('disable-gpu-shader-disk-cache');
const __filename = fileURLToPath(import.meta.url);
@@ -23,23 +48,8 @@ function log(...args) {
console.log(line.trim());
}
function parseArgs() {
const args = { docs: null, headless: false, port: null };
const docsIndex = process.argv.indexOf('--docs');
if (docsIndex !== -1 && process.argv[docsIndex + 1]) {
args.docs = process.argv[docsIndex + 1];
}
if (process.argv.includes('--headless')) {
args.headless = true;
}
const portIndex = process.argv.indexOf('--port');
if (portIndex !== -1 && process.argv[portIndex + 1]) {
args.port = parseInt(process.argv[portIndex + 1], 10);
}
return args;
}
const args = parseArgs();
process.stdout.write(`[${new Date().toISOString()}] [main] XCSDD starting in ${argsGlobal.headless ? 'HEADLESS' : 'normal'} mode\n`);
process.stdout.write(`[${new Date().toISOString()}] [main] Args: docs=${argsGlobal.docs}, headless=${argsGlobal.headless}, port=${argsGlobal.port}\n`);
function getIndexPath() {
if (app.isPackaged) {
@@ -125,14 +135,14 @@ function createWindow() {
},
});
if (args.port) {
mainWindow.loadURL(`http://localhost:${args.port}/`);
if (argsGlobal.port) {
mainWindow.loadURL(`http://localhost:${argsGlobal.port}/`);
} else {
mainWindow.loadFile(indexPath);
}
mainWindow.on('ready-to-show', () => {
if (!args.headless) {
if (!argsGlobal.headless) {
mainWindow.show();
}
});
@@ -145,10 +155,10 @@ function createWindow() {
log('Page finished loading');
});
if (!app.isPackaged && !args.headless) {
if (!app.isPackaged && !argsGlobal.headless) {
mainWindow.webContents.openDevTools();
}
mainWindow.on('closed', () => {
mainWindow = null;
});
@@ -195,11 +205,11 @@ ipcMain.on('renderer-log', (_event, level, ...args) => {
});
app.whenReady().then(() => {
log('App ready, parsing args:', args);
log('App ready, parsing args:', argsGlobal);
if (args.port) {
log('Starting HTTP server on port', args.port);
httpServer = startHttpServer(args.port);
if (argsGlobal.port) {
log('Starting HTTP server on port', argsGlobal.port);
httpServer = startHttpServer(argsGlobal.port);
}
createWindow();
@@ -218,7 +228,13 @@ app.on('window-all-closed', () => {
if (httpServer) {
httpServer.close();
}
if (process.platform !== 'darwin') {
if (argsGlobal.headless) {
log('Headless mode: window closed, keeping process alive for 5 seconds...');
setTimeout(() => {
log('Headless mode: exiting now');
process.exit(0);
}, 5000);
} else if (process.platform !== 'darwin') {
app.quit();
}
});