å¿«éè°è¯ Angular 循ç¯ä¾èµ | AIçæåç¿»è¯
é®é¢ï¼ å¦ä½å¨ Angular 21 䏿¾åºåªä¸ªç»ä»¶ææ¨¡ååå¨å¯¼å ¥æ standalone ç»ä»¶ç循ç¯é®é¢ï¼
çæ¡ï¼
å¨ Angular 21ï¼ä»¥åèª ~v14âv17 ç Ivy + standalone æ¨å¨ä»¥æ¥ï¼ï¼å¾ªç¯å¯¼å ¥é常ä¼å¯¼è´ï¼
- build-time stack overflow in
@ngtools/webpack/ esbuild - NG0919: Circular Dependency Detected
- NG0200: Circular Dependency in DI
- ReferenceError / Cannot access before initializationï¼å°¤å ¶æ¯ä½¿ç¨ standalone æ¶ï¼
以䏿¯å¨ 2026 å¹´ Angular 项ç®ä¸å®ä½ç¡®å导è´å¾ªç¯ä¾èµçæä»¶çææææ¹æ³ã
1. ä½¿ç¨ madge â 仿¯ #1 æ¨èå·¥å
·ï¼å®æ¹ Angular ææ¡£å»ºè®®ä½¿ç¨å®ï¼
# Install once (recommended as dev dep)
npm install --save-dev madge
# Quick check
npx madge --circular --extensions ts src/
# More precise (start from entry point)
npx madge --circular src/main.ts
# Show warning level too (barrels, side-effects, etc.)
npx madge --circular --warning src/
# Generate visual graph (very helpful!)
npx madge --circular --extensions ts --image deps.svg src/
# then open deps.svg in browser
-
è¾åºç¤ºä¾ï¼
â Found 3 circular dependencies! 1) src/app/featureA.component.ts â src/app/shared/utils.service.ts â src/app/featureA.component.ts 2) src/app/dashboard/dashboard.component.ts â src/app/core/auth.service.ts â src/app/dashboard/data.service.ts â src/app/dashboard/dashboard.component.ts
2. ä½¿ç¨ dependency-cruiserï¼æ´å¼ºå¤§çè§å忥ååè½ï¼
npm install --save-dev dependency-cruiser
# Initialize default config
npx depcruise --init
# Run (detects circular by default)
npx depcruise src --validate .dependency-cruiser.js
# Or focused on circular only
npx depcruise src --include-only "^src" --output-type err --ruleset .dependency-cruiser.js
许å¤å¢éå¨å¤§å monorepo 䏿´å欢å®è䏿¯ madgeï¼å 为å¯ä»¥å¨ CI ä¸å¼ºå¶æ§è¡âæ 循ç¯ä¾èµâã
3. Angular CLI + build flagsï¼å¿«é缩å°èå´ï¼
# Very verbose output â often shows file just before crash
ng build --verbose
# Or with higher stack trace
NODE_OPTIONS="--stack-trace-limit=400" ng build --verbose
# Disable incremental â sometimes reveals clearer file name
ng build --no-progress --aot
4. Standalone ç¹æç循ç¯ä¾èµï¼å¨ Angular 17â21 ä¸é常常è§ï¼
å ¸åæ¨¡å¼ï¼éå½ / ç¶ â å standalone ç»ä»¶
// parent.component.ts
imports: [ChildComponent]
// child.component.ts
imports: [ParentComponent] â direct cycle
ä½¿ç¨ forwardRef ä¿®å¤æ¨¡å¼ï¼
// child.component.ts
import { forwardRef } from '@angular/core';
imports: [forwardRef(() => ParentComponent)]
ä½è¦æ¾åºå®ä»¬ï¼
- madge ä»ç¶è½æè·å®ä»¬ï¼å®éµå¾ª ES importsï¼
- ä¸´æ¶æ³¨é
app.config.ts/ root bootstrap ä¸ç imports â é个添å 忥 -
æç´¢ä»£ç åºä¸çäºå¯¼ï¼
# rough grep (adjust paths) grep -r "imports.*Component" src/app | grep -B1 -A1 "Component"
å¿«éè¡å¨æ£æ¥æ¸ åï¼2026 æä½³å®è·µï¼
npx madge --circular --extensions ts src/ > circular.txt- æå¼
circular.txtâ å ä¿®å¤æççå¾ªç¯ - 常è§ç½ªé祸é¦ï¼
- Barrel æä»¶ï¼
index.tséæ°å¯¼åºæ¨¡å/ç»ä»¶ï¼ - Shared utils/service 被 feature ååå¯¼å ¥
- æªä½¿ç¨
forwardRefçéå½ standalone ç»ä»¶ - æ§ NgModule â standalone è¿ç§»éçé®é¢
- Barrel æä»¶ï¼
- ä¿®å¤å â è¿è¡
ng build --prod确认 -
æ·»å å°
package.jsonscriptsï¼"check-circular": "madge --circular --extensions ts src/"â å¨æäº¤å / CI ä¸è¿è¡
å³ä½¿å¨ Angular 21 ä¸ï¼madge 仿¯ Angular ç¤¾åºæå¿«ä¸ææ¨èçå·¥å ·ã
åèï¼
- https://angular.dev/errors/NG0919
- https://medium.com/@vkrntteotia/how-to-automatically-detect-circular-dependencies-in-your-angular-project-using-a-tool-called-madge-9c2f8ab77b4f
- https://timdeschryver.dev/blog/fixing-angular-standalone-components-that-have-a-circular-dependency
- https://www.npmjs.com/package/madge
- https://github.com/sverweij/dependency-cruiser
