Watch mode (`ng test`, `ng serve`) stalls after "Watch mode enabled" when `preserveSymlinks: true` — chokidar scans entire workspace incl. `node_modules` (regression in 22.2.0)
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 58/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- angular, typescript
- Ambito
- build-system, cli, testing-qa
Direzione di ricerca
Start in src/builders/application/build-action.js and src/utils/watcher.js, tracing setupWatcher(), createWatcher(), and createChokidarWatcher() for preserveSymlinks: true. Use the linked reproduction or the listed npx and ng test commands on Windows, then verify that ng test, ng serve, and ng build --watch no longer wait on an unnecessarily broad initial scan before the first result.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Command
- test
- serve
Is this a regression?
- Yes, this behavior used to work in the previous version
The previous version in which this bug was not present was
22.1.8
Description
(AI generated)
After updating @angular/build / @angular/cli from 22.1.8 to 22.2.0, ng test in watch mode (@angular/build:unit-test, Vitest runner) no longer starts running tests after the initial build when the build target has "preserveSymlinks": true. The output stops at:
Application bundle generation complete. [52.899 seconds]
Watch mode enabled. Watching for file changes...
With NG_TEST_LOG=1, VitestExecutor never logs Executing test run — the first build result is not handed to the executor. We stopped the process after more than 4 minutes of waiting. ng test --watch=false is unaffected (the full suite finishes in ~3 min including the build).
Setting "preserveSymlinks": false in the test build configuration makes Vitest start ~2 s after the build completes. Downgrading Vitest (5.0.1 → 4.1.11) makes no difference, so it is not Vitest-related.
Cause (from reading @angular/build 22.2.0 sources):
In src/builders/application/build-action.js, watch mode now calls setupWatcher() from src/utils/watcher.js before emitting the first build result:
createWatcher()uses chokidar instead of@parcel/watcherwheneverfollowSymlinks(=preserveSymlinks) is true.createChokidarWatcher()callschokidar.watch(rootDir, …)on the entire workspace root (cwd: workspaceRoot), regardless ofNG_BUILD_WATCH_ROOT.- The
**/node_modules/**ignore pattern is only added whenshouldWatchRoot && !preserveSymlinks, so withpreserveSymlinks: truechokidar also walks all ofnode_modules(≈106 000 files in our workspace). - It then does
await once(watcher, 'ready')(added in #34122), i.e. it blocks until that full initial scan has completed — withfollowSymlinks: trueon Windows.
In 22.1.8, build-action.js used tools/esbuild/watcher.js and only watched the files/directories from result.watchFiles (plus the project root only if NG_BUILD_WATCH_ROOT was set), with no wait for an initial scan, so startup was instant.
preserveSymlinks: true is a common setting for workspaces that npm link local libraries, so this effectively makes watch mode unusable for them.
Since ng serve and ng build --watch go through the same runEsBuildBuildAction / setupWatcher path, they are affected as well, see comment below.
Possible fixes:
- Keep watching only
watchFiles(and the root only withNG_BUILD_WATCH_ROOT), as in 22.1.8, for the chokidar path; or - ignore
node_modulesunder the workspace root in the chokidar path as well — explicitly added watch files outside the root (e.g.npm linktargets) would still be watched; or - don't block the first build result on chokidar's
readywhen the initial scan is large.
Minimal Reproduction
Verified by me (human): https://github.com/reifi/angular-preserve-symlinks-watch-repro
Reproducible with a freshly generated project:
npx @angular/[email protected] new repro --defaults --test-runner=vitest- In
angular.json, add"preserveSymlinks": truetoprojects.repro.architect.build.options. - Run
ng test(watch mode;ng test --watchin a non-TTY shell). - Observe: output stops after "Watch mode enabled. Watching for file changes..." for about 2 minutes before Vitest starts.
Measured on Windows 11, fresh project (≈18 000 files in node_modules), time from "Watch mode enabled" to the Vitest test summary:
preserveSymlinks |
Time to test summary | Vitest run duration |
|---|---|---|
| not set (default) | 6 s | 5.3 s |
true |
123 s | 7.0 s |
The delay scales with the number of files under the workspace root. In a large application workspace (≈106 000 files in node_modules) tests had still not started after more than 4 minutes, when we stopped the process. ng test --watch=false is not affected.
Exception or Error
No error — the process hangs silently after:
Watch mode enabled. Watching for file changes...
Your Environment
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI : 22.2.0
Angular : 22.2.0
Node.js : 26.8.2
Package Manager : npm 11.19.1
Operating System : win32 x64
┌─────────────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├─────────────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build │ 22.2.0 │ ^22.2.0 │
│ @angular/cdk │ 22.2.0 │ ^22.2.0 │
│ @angular/cli │ 22.2.0 │ ^22.2.0 │
│ @angular/common │ 22.2.0 │ ^22.2.0 │
│ @angular/compiler │ 22.2.0 │ ^22.2.0 │
│ @angular/compiler-cli │ 22.2.0 │ ^22.2.0 │
│ @angular/core │ 22.2.0 │ ^22.2.0 │
│ @angular/forms │ 22.2.0 │ ^22.2.0 │
│ @angular/google-maps │ 22.2.0 │ ^22.2.0 │
│ @angular/localize │ 22.2.0 │ ^22.2.0 │
│ @angular/material │ 22.2.0 │ ^22.2.0 │
│ @angular/material-luxon-adapter │ 22.2.0 │ ^22.2.0 │
│ @angular/platform-browser │ 22.2.0 │ ^22.2.0 │
│ @angular/router │ 22.2.0 │ ^22.2.0 │
│ @angular/upgrade │ 22.2.0 │ ^22.2.0 │
│ rxjs │ 7.8.2 │ ^7.8.2 │
│ typescript │ 6.0.3 │ ^6.0.3 │
│ vitest │ 5.0.1 │ ^5.0.1 │
│ zone.js │ 0.16.3 │ ^0.16.3 │
└─────────────────────────────────┴───────────────────┴───────────────────┘
Anything else relevant?
Workaround: override "preserveSymlinks": false in the build configuration referenced by the unit-test buildTarget, e.g.
"configurations": {
"test": {
"preserveSymlinks": false,
…
}
}
The unit-test builder reads preserveSymlinks from the build target options (unit-test/options.js), so this only affects tests; ng serve / ng build keep preserveSymlinks: true for npm link.
- Lingua principale
- TypeScript
- Stelle
- 27k
- Fork
- 11.8k
- Merge medio
- 17h 47m
- PR unite (30g)
- 181
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di angular/angular-cli
-
area: @angular/build gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
angular/angular-cli#33955 ·
-
area: @angular/cli gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
angular/angular-cli#33055 · 1 commento · 3 reazioni ·
-
area: @angular/build gemini-triaged
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
angular/angular-cli#34166 · 1 commento ·
-
Angular CLI can copy files from outside the workspace root through symlinked asset directories Apertaarea: @angular/build gemini-triaged
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
angular/angular-cli#34164 ·
-
area: @angular/build gemini-triaged severity5: regression
Difficoltà 4/5 3-5 giorni Idoneità per principianti 75/100
angular/angular-cli#34163 ·
Tutte le issue di angular/angular-cli
Issue simili
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
motiondivision/motion#3849 ·
-
Add: S Play Event HD Apertacheck:passed streams:add
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
LiteLLM proxy response_cost (x-litellm-response-cost) is never applied to ChatModelOutput.cost Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
i-am-bee/beeai-framework#1697 · 1 reazione ·
-
Support bun dedupe Apertaenhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
antfu/node-modules-inspector#214 ·