錯誤百科

偵測到循環依賴

Angular 偵測到元件、指令或管道之間存在循環依賴。當元件 A 匯入元件 B,而元件 B(直接或間接)匯入元件 A,形成循環時,就會發生此錯誤。

這種循環參照會讓 Angular 無法正確初始化元件,導致像這樣的錯誤:

NG0919: Cannot read @Component metadata. This can indicate a runtime circular dependency in your app that needs to be resolved.

在較舊的 Angular 版本中,你可能會改看到像這樣的錯誤:

Cannot read properties of undefined (reading 'ɵcmp')

常見成因

元件互相匯入

最常見的成因是兩個元件互相匯入:

parent.ts

import {Component} from '@angular/core';
import {Child} from './child';

@Component({
  selector: 'app-parent',
  imports: [Child],
  template: '<app-child/>',
})
export class Parent {}

child.ts

import {Component} from '@angular/core';
import {Parent} from './parent';

@Component({
  selector: 'app-child',
  imports: [Parent],
  template: '<app-parent/>',
})
export class Child {}

間接循環參照

循環依賴也可能透過中間檔案發生:

ComponentA -> ComponentB -> ComponentC -> ComponentA

解決方式

重構共用邏輯

把共用功能移到一個不匯入任一元件的獨立檔案中:

shared.service.ts

import {Service} from '@angular/core';

@Service()
export class SharedService {
  // Shared logic here
}

使用僅型別匯入

如果你只需要 TypeScript 的型別,請使用 import type:

import type {Parent} from './parent';

僅型別匯入會在編譯時期被抹除,不會造成執行時期的循環依賴。

重構元件階層

思考循環依賴是否意味著設計上的問題。通常,把共用功能抽出到第三個元件或服務是最乾淨的解法。

為複雜的循環依賴除錯

對於有許多模組的複雜應用程式,手動找出循環依賴可能很困難。可以考慮使用像 madge 這類工具來視覺化並偵測循環匯入:

# Install madge
npm install -g madge

# Check for circular dependencies
madge --circular --extensions ts ./src

# Generate a visual graph
madge --circular --extensions ts --image graph.svg ./src

這些工具可以協助找出整個專案中的循環依賴鏈,並產生視覺化的依賴圖。