Circular dependency detected
モジュール間で循環依存が検出された場合のエラー
概要
モジュールA→モジュールB→モジュールAのように、モジュール間で循環的なインポート関係が発生した場合のエラーです。バンドラーや実行時に問題を引き起こします。
エラーメッセージ
Circular dependency detected:
src/moduleA.js -> src/moduleB.js -> src/moduleA.js
Warning: Circular dependency: src/utils/index.js -> src/utils/helper.js -> src/utils/index.js
RangeError: Maximum call stack size exceeded
TypeError: Cannot read property 'xxx' of undefined
原因
- 相互依存: 2つのモジュールが互いにインポート
- 間接的な循環: A→B→C→Aのような間接的な依存
- バレルファイル: index.jsからの再エクスポートによる循環
- 設計上の問題: 責務の分離ができていない
解決策
1. 依存関係を可視化
| |
2. 共通モジュールを抽出
| |
3. インターフェース/型を分離
| |
4. 遅延インポート(動的インポート)
| |
5. 依存性注入
| |
6. バレルファイルの注意点
| |
7. 層の分離(レイヤードアーキテクチャ)
// 正しい依存方向
Controllers → Services → Repositories → Models
// 上位層から下位層へのみ依存
// 下位層は上位層を知らない
| |
8. イベントバスパターン
| |
9. NestJSでのforwardRef
| |
10. ESLintで検出
| |
11. Webpackで検出
| |
設計原則
| 原則 | 説明 |
|---|---|
| 単一責任原則 | 1モジュール = 1責務 |
| 依存性逆転原則 | 抽象に依存、具象に依存しない |
| 層の分離 | 上位→下位の一方向依存 |
よくある間違い
- 便利だからとindex.jsから全てエクスポート
- ユーティリティ関数を1つのファイルにまとめすぎる
- 双方向の参照が必要な設計をしてしまう
- 警告を無視して開発を続ける
関連エラー
参考リンク
JavaScript の他のエラー
この記事は役に立ちましたか?