element-hq / element-hq/element-web
nx build:ts cache outputs miss lib/preload.cjs, so a cache-replayed desktop build ships without the preload and falls back to the web platform
- Dominant language
- TypeScript
- Stars
- 13.5k
- Forks
- 2.8k
- PR merge metrics
- PR metrics pending
Description
### Steps to reproduce
1. `pnpm exec nx build:ts element-desktop` once, so the nx cache has an entry for the target.
2. `rm -rf apps/desktop/lib` (or check out a fresh copy that shares the same nx cache, e.g. a CI runner with remote cache or a second worktree).
3. `pnpm exec nx build:ts element-desktop` again. nx reports the task as replayed from cache instead of running `tsc`.
4. `ls apps/desktop/lib` - or package the app and run `pnpm exec asar list dist/win-unpacked/resources/app.asar | grep preload`.
### Outcome
#### What did you expect?
`lib/` after a cache replay is identical to `lib/` after a real `tsc` run, including `preload.cjs`.
#### What happened instead?
`lib/preload.cjs` (and `preload.d.cts`) are missing. Everything else is restored.
`apps/desktop/project.json` declares the cacheable outputs of `build:ts` as
```json
"outputs": ["{projectRoot}/lib/*.js", "{projectRoot}/lib/*.d.ts"]
```
but `apps/desktop/tsconfig.json` includes `./src/**/*.cts`, and `src/preload.cts` is emitted as `lib/preload.cjs` + `lib/preload.d.cts`. Neither matches the output globs, so nx never stores them in the cache and a cache hit restores everything except the preload script.
The packaged app then starts without a preload, so `window.electron` is undefined and the renderer silently falls back to the **web** platform. User-visible symptoms are confusing and do not point at the build:
- a "Failed to load service worker" toast on startup,
- no call buttons / Element Call unavailable, screen sharing does nothing,
- `Element.exe --enable-logging=stderr` shows `Unable to load preload script: ...app.asar\lib\preload.cjs`, `ENOENT, lib\preload.cjs not found`, then `Using Web platform`.
Nothing in the electron-builder step fails, so the broken installer ships.
#### Fix
Add the `.cts` emit to the outputs:
```json
"outputs": [
"{projectRoot}/lib/*.js",
"{projectRoot}/lib/*.d.ts",
"{projectRoot}/lib/*.cjs",
"{projectRoot}/lib/*.d.cts"
]
```
I have carried this one-line change in a fork since 1.12.18 and can open a PR.
### Operating system
Windows 11 Pro (10.0.26200); the cache logic is platform-independent.
### Application version
`develop` at 9a536a3419 (1.12.27), nx 23.1.2, pnpm 11.23.0.
### How did you install the app?
Built from source (`nx build:ts` + `electron-builder --win squirrel`).
### Homeserver
n/a
### Will you send logs?
Included above.
Contributor guide
Research direction
Start with apps/desktop/project.json and compare its build:ts outputs with the .cts entry in apps/desktop/tsconfig.json. Run pnpm exec nx build:ts element-desktop, remove apps/desktop/lib, and run it again to verify the cache replay restores preload.cjs and preload.d.cts. Done means the replayed lib/ matches a real tsc build and the packaged app contains the preload script.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, typescript
- Domain
- build-system, desktop
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100