mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
perf(electron): defer fixPath() off the synchronous startup path
fixPath() was called as the very first statement at module load (top-level, before app.setName, before app.whenReady), which on macOS/Linux spawns an interactive login shell — bash/zsh -ilc 'env' — and waits SYNCHRONOUSLY for it to print the environment back. With oh-my-zsh / heavy .bashrc setups this is routinely 50-300ms blocking the Electron main process before window creation can even begin. The only purpose of fixPath in this app is to populate process.env.PATH so that subsequently-spawned external player binaries (MPV/VLC) can be resolved by bare name. That's a user-action path (clicking play with external player configured), not a startup-critical one. Two callers exist (player.events.ts) and both fall back to bare 'mpv' / 'vlc' only after checking well-known absolute paths. Move the call into a setImmediate scheduled at the END of bootstrapAppEvents — after DB init, IPC handler registration, and window load. The user-visible startup sequence no longer carries the shell-spawn cost. By the time anyone could plausibly click an external player, PATH is already hydrated. Idempotent + Windows-gated (fix-path is a no-op on Windows anyway). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: f957cd9849e0
This commit is contained in:
1 parent
cf30c129f1
commit
177148ad5d
1 file changed
+37
-2
@@ -32,6 +32,34 @@ if (electronUserDataPath) {
|
||||
app.setPath('userData', electronUserDataPath);
|
||||
}
|
||||
|
||||
let fixPathScheduled = false;
|
||||
|
||||
/**
|
||||
* Update process.env.PATH from the user's interactive login shell so that
|
||||
* spawned external players (MPV/VLC) can be resolved by binary name.
|
||||
*
|
||||
* Runs after window creation + IPC handler registration so the 50-300 ms
|
||||
* shell-spawn cost (bash/zsh -ilc env) doesn't block startup. Idempotent:
|
||||
* subsequent calls are no-ops.
|
||||
*/
|
||||
function scheduleDeferredFixPath(): void {
|
||||
if (fixPathScheduled || process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
|
||||
fixPathScheduled = true;
|
||||
setImmediate(() => {
|
||||
try {
|
||||
fixPath();
|
||||
if (isStartupTraceEnabled()) {
|
||||
trace('startup', 'fix-path:done');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('fix-path failed:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default class Main {
|
||||
static initialize() {
|
||||
if (SquirrelEvents.handleEvents()) {
|
||||
@@ -89,11 +117,18 @@ export default class Main {
|
||||
if (isStartupTraceEnabled()) {
|
||||
trace('startup', 'bootstrap-events:done');
|
||||
}
|
||||
|
||||
// Hydrate process.env.PATH from the user's login shell now — after
|
||||
// the window has loaded and IPC handlers are live. Fire-and-forget
|
||||
// (setImmediate) so it doesn't gate any user-visible work. Worst
|
||||
// case: the user clicks an external player within the ~100 ms it
|
||||
// takes to complete; the spawn would still find MPV/VLC at any of
|
||||
// the well-known paths checked by getDefault*Path before falling
|
||||
// back to bare-name PATH lookup.
|
||||
scheduleDeferredFixPath();
|
||||
}
|
||||
}
|
||||
|
||||
fixPath();
|
||||
|
||||
// handle setup events as quickly as possible
|
||||
Main.initialize();
|
||||
|
||||
|
||||
Reference in new issue
Block a user