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)
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 58/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- angular, typescript
- Lĩnh vực
- build-system, cli, testing-qa
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- TypeScript
- Star
- 27k
- Fork
- 11.8k
- Merge trung bình
- 17 giờ 47 phút
- Pull request đã merge (30 ngày)
- 181
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của angular/angular-cli
-
Can't use an array of hostnames in --allowedHosts cli parameter in @angular/build:dev-server Đang mởarea: @angular/build gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
angular/angular-cli#33955 ·
-
area: @angular/cli gemini-triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
angular/angular-cli#33055 · 1 bình luận · 3 reaction ·
-
area: @angular/build gemini-triaged
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
angular/angular-cli#34166 · 1 bình luận ·
-
Angular CLI can copy files from outside the workspace root through symlinked asset directories Đang mởarea: @angular/build gemini-triaged
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 52/100
angular/angular-cli#34164 ·
-
area: @angular/build gemini-triaged severity5: regression
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 75/100
angular/angular-cli#34163 ·
Tất cả issue của angular/angular-cli
Issue tương tự
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 88/100
motiondivision/motion#3849 ·
-
Add: S Play Event HD Đang mởcheck:passed streams:add
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
Improvement for contact popover Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
-
LiteLLM proxy response_cost (x-litellm-response-cost) is never applied to ChatModelOutput.cost Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
i-am-bee/beeai-framework#1697 · 1 reaction ·
-
Support bun dedupe Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
antfu/node-modules-inspector#214 ·