Before submitting
Area
Build, CI, or release tooling
Steps to reproduce
pnpm dist:desktop:win on Windows 11 x64 (measured at main @ ba9c9ae; re-checked at 02f4ce5)
- Count the files in the NSIS payload:
7z e release/T3-Code-*-x64.exe '$PLUGINSDIR/app-64.7z' then 7z l -slt app-64.7z
- Install the result, and time the first launch
Expected behavior
The installer writes roughly the number of files the app actually needs on disk, and a cold start is not dominated by module loading.
Actual behavior
The Windows installer writes 14,687 files. 13,875 of them are loose node_modules files under app.asar.unpacked. Only 20 are native .node binaries. For contrast, the entire Electron runtime — several hundred MB — is 22 files, because it stays inside the archive.
|
files |
| total written at install |
14,687 |
app.asar.unpacked/node_modules |
13,875 |
app.asar.unpacked/apps/server/dist |
790 |
| everything else, incl. the Electron runtime |
22 |
genuinely native .node binaries |
20 |
The cause is WINDOWS_ASAR_UNPACK in scripts/build-desktop-artifact.ts:
export const WINDOWS_ASAR_UNPACK = ["apps/server/dist/**", "**/node_modules/**"] as const;
That blanket unpack is load-bearing today: the CLI bundle externalizes its runtime dependencies, and the WSL backend launches plain wsl.exe -- node, which cannot read inside an asar. So every external dep has to be a real file.
This costs twice:
- Install. NSIS install time tracks file count, not bytes.
- Cold start. Each of those files is a separate open/stat/scan the first time the server runs after an install — exactly when the OS file cache is cold and the on-access scanner is not.
Inverting the bundler's rule — bundle everything except what genuinely cannot be inlined (native addons, the JS wrappers that dlopen them, and the Bun-only entry points resolving bun:*) — lets asarUnpack narrow to that set:
|
before |
after |
| files written at install |
14,687 |
1,192 (−92%) |
loose node_modules files |
13,875 |
370 |
native .node binaries |
20 |
20 |
| installer size |
145.0 MiB |
138.9 MiB |
Cold start improves by the same mechanism. Extracting each build's payload to a fresh directory (so the files have never been read) and booting the server, alternating run order between builds so cache and scanner state could not favour either one:
|
before |
after |
server boot to Listening on |
9,044ms / 10,160ms |
3,667ms / 3,779ms |
module load only (--version) |
6,521 / 6,238 / 6,208ms |
761 / 659 / 654ms |
The main window is not created until the backend answers HTTP, so that ~6s comes straight off a cold launch.
Second, unrelated issue in the same area. installWindowsEnvironment in apps/desktop/src/shell/DesktopShellEnvironment.ts spawns PowerShell twice in series at offset 0 of desktop.startup, before anything else runs. The two probes are independent — only their results are combined. Traces over this code path measured them at 2718ms then 2066ms: the whole 4.8s startup span, of which desktop.bootstrap is ~30ms.
Why this is Windows-only: asarUnpack is gated to platform === "win". macOS and Linux use electron-builder's smart unpack and stay packed, so none of this is visible there.
Impact
Major degradation or frequent failure
Version or commit
main @ ba9c9ae (re-verified against 02f4ce5)
Environment
Windows 11 Enterprise 26220, x64, Node 24.18.0, pnpm 11.10.0, electron-builder win/nsis
Workaround
None from the user side; it's in the packaging config.
Before submitting
Area
Build, CI, or release tooling
Steps to reproduce
pnpm dist:desktop:winon Windows 11 x64 (measured atmain@ ba9c9ae; re-checked at 02f4ce5)7z e release/T3-Code-*-x64.exe '$PLUGINSDIR/app-64.7z'then7z l -slt app-64.7zExpected behavior
The installer writes roughly the number of files the app actually needs on disk, and a cold start is not dominated by module loading.
Actual behavior
The Windows installer writes 14,687 files. 13,875 of them are loose
node_modulesfiles underapp.asar.unpacked. Only 20 are native.nodebinaries. For contrast, the entire Electron runtime — several hundred MB — is 22 files, because it stays inside the archive.app.asar.unpacked/node_modulesapp.asar.unpacked/apps/server/dist.nodebinariesThe cause is
WINDOWS_ASAR_UNPACKinscripts/build-desktop-artifact.ts:That blanket unpack is load-bearing today: the CLI bundle externalizes its runtime dependencies, and the WSL backend launches plain
wsl.exe -- node, which cannot read inside an asar. So every external dep has to be a real file.This costs twice:
Inverting the bundler's rule — bundle everything except what genuinely cannot be inlined (native addons, the JS wrappers that
dlopenthem, and the Bun-only entry points resolvingbun:*) — letsasarUnpacknarrow to that set:node_modulesfiles.nodebinariesCold start improves by the same mechanism. Extracting each build's payload to a fresh directory (so the files have never been read) and booting the server, alternating run order between builds so cache and scanner state could not favour either one:
Listening on--version)The main window is not created until the backend answers HTTP, so that ~6s comes straight off a cold launch.
Second, unrelated issue in the same area.
installWindowsEnvironmentinapps/desktop/src/shell/DesktopShellEnvironment.tsspawns PowerShell twice in series at offset 0 ofdesktop.startup, before anything else runs. The two probes are independent — only their results are combined. Traces over this code path measured them at 2718ms then 2066ms: the whole 4.8s startup span, of whichdesktop.bootstrapis ~30ms.Why this is Windows-only:
asarUnpackis gated toplatform === "win". macOS and Linux use electron-builder's smart unpack and stay packed, so none of this is visible there.Impact
Major degradation or frequent failure
Version or commit
main @ ba9c9ae (re-verified against 02f4ce5)
Environment
Windows 11 Enterprise 26220, x64, Node 24.18.0, pnpm 11.10.0, electron-builder win/nsis
Workaround
None from the user side; it's in the packaging config.