forked from aackerman/circular-dependency-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
107 lines (92 loc) · 3.51 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
let path = require('path')
let extend = require('util')._extend
let Graph = require('tarjan-graph')
let BASE_ERROR = 'Circular dependency detected:\r\n'
let PluginTitle = 'CircularDependencyPlugin'
class CircularDependencyPlugin {
constructor(options) {
this.options = extend({
exclude: new RegExp('$^'),
include: new RegExp('.*'),
failOnError: false,
allowAsyncCycles: false,
onDetected: false,
cwd: process.cwd()
}, options)
}
apply(compiler) {
let plugin = this
let cwd = this.options.cwd
compiler.hooks.compilation.tap(PluginTitle, (compilation) => {
compilation.hooks.optimizeModules.tap(PluginTitle, (modules) => {
if (plugin.options.onStart) {
plugin.options.onStart({ compilation });
}
const dependencyGraph = new Graph()
//console.log('LENGTH', modules.length);
for (let module of modules) {
// Iterate over the current modules dependencies
const dependedModuleIds = [];
for (let dependency of module.dependencies) {
let depModule = null
if (compilation.moduleGraph) {
// handle getting a module for webpack 5
depModule = compilation.moduleGraph.getModule(dependency)
} else {
// handle getting a module for webpack 4
depModule = dependency.module
}
if (!depModule) { continue }
// ignore dependencies that don't have an associated resource
if (!depModule.resource) { continue }
// optionally ignore dependencies that are resolved asynchronously
if (this.options.allowAsyncCycles && dependency.weak) { continue }
dependedModuleIds.push(depModule.identifier());
}
dependencyGraph.add(module.identifier(), dependedModuleIds)
}
const cycles = dependencyGraph.getCycles();
cycles.forEach((vertices) => {
// Convert the array of vertices into an array of module paths
const cyclicAbsolutePaths = vertices
.slice()
.reverse()
.map((vertex) => compilation.findModule(vertex.name).resource);
if (cyclicAbsolutePaths.every((resource) => (
resource == null ||
plugin.options.exclude.test(resource) ||
!plugin.options.include.test(resource)
))) {
// If all modules in the cycle are excluded by the config, don't report an error
return;
}
const cyclicPaths = cyclicAbsolutePaths.map((resource) => path.relative(cwd, resource));
// allow consumers to override all behavior with onDetected
if (plugin.options.onDetected) {
try {
plugin.options.onDetected({
module: module,
paths: cyclicPaths.concat([cyclicPaths[0]]),
compilation: compilation
})
} catch(err) {
compilation.errors.push(err)
}
return
}
// mark warnings or errors on webpack compilation
let error = new Error(BASE_ERROR.concat(cyclicPaths.concat([cyclicPaths[0]]).join(' -> ')))
if (plugin.options.failOnError) {
compilation.errors.push(error)
} else {
compilation.warnings.push(error)
}
});
if (plugin.options.onEnd) {
plugin.options.onEnd({ compilation });
}
})
})
}
}
module.exports = CircularDependencyPlugin