refactor(electron): bundle preload script with esbuild to support sandbox mode

Bundle preload.ts into a single file so all local imports (e.g.
ipc-events.const) are inlined at build time. This allows removing
sandbox: false since the bundled preload only requires the built-in
electron module, which is allowed in sandboxed preloads.
This commit is contained in:
Johannes Millan 2026-03-22 19:38:21 +01:00
parent 815341d5e8
commit a118f65d54
4 changed files with 17 additions and 5 deletions

1
.gitignore vendored
View file

@ -75,6 +75,7 @@ src/app/**/*.js.map
# added # added
build/hub build/hub
electron/**/*.js electron/**/*.js
!electron/scripts/bundle-preload.js
electron/**/*.js.map electron/**/*.js.map
# mac os deployment # mac os deployment

View file

@ -124,10 +124,6 @@ export const createWindow = async ({
webSecurity: false, webSecurity: false,
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false, nodeIntegration: false,
// Required: preload.js uses require() for local modules (e.g. ./shared-with-frontend/ipc-events.const).
// Electron 20+ defaults sandbox to true, and sandboxed preloads can only require built-in Electron
// modules. This does NOT disable Chromium's OS-level process sandbox (that's --no-sandbox).
sandbox: false,
// make remote module work with those two settings // make remote module work with those two settings
contextIsolation: true, contextIsolation: true,
// Additional settings for better Linux/Wayland compatibility // Additional settings for better Linux/Wayland compatibility

View file

@ -0,0 +1,15 @@
#!/usr/bin/env node
const { build } = require('esbuild');
const path = require('path');
build({
entryPoints: [path.join(__dirname, '..', 'preload.ts')],
bundle: true,
outfile: path.join(__dirname, '..', 'preload.js'),
platform: 'node',
target: 'es2022',
format: 'cjs',
external: ['electron'],
sourcemap: false,
logLevel: 'info',
}).catch(() => process.exit(1));

View file

@ -71,7 +71,7 @@
"e2e:docker:webdav": "docker compose -f docker-compose.e2e.yaml up -d app webdav && ./scripts/wait-for-app.sh && ./scripts/wait-for-webdav.sh && E2E_BASE_URL=http://localhost:${APP_PORT:-4242} npm run e2e:all -- --grep @webdav; docker compose -f docker-compose.e2e.yaml down", "e2e:docker:webdav": "docker compose -f docker-compose.e2e.yaml up -d app webdav && ./scripts/wait-for-app.sh && ./scripts/wait-for-webdav.sh && E2E_BASE_URL=http://localhost:${APP_PORT:-4242} npm run e2e:all -- --grep @webdav; docker compose -f docker-compose.e2e.yaml down",
"e2e:docker:all": "docker compose -f docker-compose.e2e.yaml -f docker-compose.yaml -f docker-compose.supersync.yaml up -d app webdav db supersync && ./scripts/wait-for-app.sh && ./scripts/wait-for-webdav.sh && ./scripts/wait-for-supersync.sh && E2E_BASE_URL=http://localhost:${APP_PORT:-4242} npm run e2e:all -- --workers=6; EXIT_CODE=$?; docker compose -f docker-compose.e2e.yaml -f docker-compose.yaml -f docker-compose.supersync.yaml down; exit $EXIT_CODE", "e2e:docker:all": "docker compose -f docker-compose.e2e.yaml -f docker-compose.yaml -f docker-compose.supersync.yaml up -d app webdav db supersync && ./scripts/wait-for-app.sh && ./scripts/wait-for-webdav.sh && ./scripts/wait-for-supersync.sh && E2E_BASE_URL=http://localhost:${APP_PORT:-4242} npm run e2e:all -- --workers=6; EXIT_CODE=$?; docker compose -f docker-compose.e2e.yaml -f docker-compose.yaml -f docker-compose.supersync.yaml down; exit $EXIT_CODE",
"electron": "NODE_ENV=PROD electron .", "electron": "NODE_ENV=PROD electron .",
"electron:build": "tsc -p electron/tsconfig.electron.json", "electron:build": "tsc -p electron/tsconfig.electron.json && node electron/scripts/bundle-preload.js",
"electron:watch": "tsc -p electron/tsconfig.electron.json --watch", "electron:watch": "tsc -p electron/tsconfig.electron.json --watch",
"electronBuilderOnly": "electron-builder", "electronBuilderOnly": "electron-builder",
"empty": "echo 'EMPTY YEAH'", "empty": "echo 'EMPTY YEAH'",