Detects circular import dependencies between modules that will exist at runtime. Import cycles are often not indicative of a bug when used by functions called at runtime, but may cause bugs or errors when the imports are used during initialization. This plugin does not distinguish between the two, but can be used to help identify and resolve cycles after a bug has been encountered.
This plugin is an adaptation of the original circular-dependency-plugin for Webpack and diverges in both behavior and features.
Because CircularDependencyRspackPlugin is implemented in Rust, it is able to integrate directly with the module graph and avoid expensive copying and serialization. On top of that, this plugin operates using a single traversal of the module graph for each entrypoint to identify all cycles rather than checking each module individually. Combined, that means CircularDependencyRspackPlugin is able to run fast enough to be part of a hot reload development cycle without any noticeable impact on reload times, even for extremely large projects with hundreds of thousands of modules and imports.
CircularDependencyRspackPlugin aims to be compatible with the features of circular-dependency-plugin, with modifications to give finer control over cycle detection and behavior.
One notable difference between the two is the use of module identifiers for cycle entries in Rspack rather than relative paths. Identifiers represent the entire unique name for a bundled module, including the set of loaders that processed it, the absolute module path, and any request parameters that were provided when importing. While matching on just the path of the module is still possible, identifiers allow for matching against loaders and rulesets as well.
This plugin also provides a new option, ignoredConnections to allow for more granular control over whether a cycle is ignored. The exclude option from the original plugin is still implemented to match existing behavior, but causes any cycle containing the module to be ignored entirely. When only specific cycles are meant to be ignored, ignoredConnections allows for specifying both a from and a to pattern to match against, ignoring only cycles where an explicit dependency between two modules is present.
node_modules, and emitting compilation errors for each cycle.to any module matching a given pattern.import('some/module')) and manually handle all detected cycles.booleanfalseWhen true, detected cycles will generate Error level diagnostics rather than Warnings. This will have no noticeable effect in watch mode, but will cause full builds to fail when the errors are emitted.
booleanfalseAllow asynchronous imports and connections to cause a detected cycle to be ignored. Asynchronous imports include import() function calls, weak imports for lazy compilation, hot module connections, and more.
RegExpundefinedSimilar to exclude from the original circular-dependency-plugin, detected cycles containing any module resource path that matches this pattern will be ignored.
Array<[string | RegExp, string | RegExp]>[]A list of explicit connections that should cause a detected cycle to be ignored. Each entry in the list represents a connection as [from, to], matching any connection where from depends on to.
Each pattern can be represented as either a plain string or a RegExp. Plain strings will be matched as substrings against the module identifier for that part of a connection, and RegExps will match anywhere in the entire identifier. For example:
'some/module/' will match any module in the some/module directory, like some/module/a and some/module/b.!file-loader!.*\.mdx will match any .mdx module processed by file-loader.(entrypoint: string, modules: string[], compilation: Compilation) => voidundefinedHandler function called for every detected cycle. Providing this handler overrides the default behavior of adding diagnostics to the compilation, meaning the value of failOnError will be effectively unused.
This handler can be used to process detected cycles further before emitting warnings or errors to the compilation, or to handle them in any other way not directly implemented by the plugin.
entrypoint is the name of the entry where this cycle was detected. Because of how entrypoints are traversed for cycle detection, it's possible that the same cycle will be detected multiple times, once for each entrypoint.
modules is the list of identifiers of module contained in the cycle, where both the first and the last entry of the list will always be the same module, and the only module that is present more than once in the list.
compilation is the full Compilation object, allowing the handler to emit errors or inspect any other part of the bundle as needed.
(entrypoint: string, modules: string[], compilation: Compilation) => voidundefinedHandler function called for every detected cycle that was intentionally ignored, whether by the exclude pattern, any match of an ignoredConnection, or any other possible reason.
(compilation: Compilation) => voidundefinedHook function called immediately before cycle detection begins, useful for setting up temporary state to use in the onDetected handler or logging progress.
(compilation: Compilation) => voidundefinedHook function called immediately after cycle detection finishes, useful for cleaning up temporary state or logging progress.