1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
8 |
|
9 | var _path = require('path');
|
10 |
|
11 | var _path2 = _interopRequireDefault(_path);
|
12 |
|
13 | var _findRoot = require('find-root');
|
14 |
|
15 | var _findRoot2 = _interopRequireDefault(_findRoot);
|
16 |
|
17 | var _webpackSources = require('webpack-sources');
|
18 |
|
19 | var _webpackSources2 = _interopRequireDefault(_webpackSources);
|
20 |
|
21 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
22 |
|
23 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
24 |
|
25 | var ConcatSource = _webpackSources2.default.ConcatSource;
|
26 | var isProducation = process.env.NODE_ENV === 'production';
|
27 |
|
28 | function cleanPath(path) {
|
29 | return path.split('/node_modules/').join('/~/');
|
30 | }
|
31 |
|
32 |
|
33 | function getClosestPackage(modulePath) {
|
34 | var root;
|
35 | var pkg;
|
36 |
|
37 |
|
38 | try {
|
39 | root = (0, _findRoot2.default)(modulePath);
|
40 | pkg = require(_path2.default.join(root, 'package.json'));
|
41 | } catch (e) {
|
42 | return null;
|
43 | }
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | if (!pkg.name) {
|
50 | return getClosestPackage(_path2.default.resolve(root, '..'));
|
51 | }
|
52 |
|
53 | return {
|
54 | package: pkg,
|
55 | path: root
|
56 | };
|
57 | }
|
58 |
|
59 | function check(compilation, modulesToCheck) {
|
60 | var context = compilation.compiler.context;
|
61 | var modules = {};
|
62 |
|
63 | function cleanPathRelativeToContext(modulePath) {
|
64 | var cleanedPath = cleanPath(modulePath);
|
65 |
|
66 |
|
67 | if (cleanedPath.indexOf(context) === 0) {
|
68 | cleanedPath = '.' + cleanedPath.replace(context, '');
|
69 | }
|
70 |
|
71 | return cleanedPath;
|
72 | }
|
73 |
|
74 | compilation.modules.forEach(function (module) {
|
75 | if (!module.resource) {
|
76 | return;
|
77 | }
|
78 |
|
79 | var pkg;
|
80 | var packagePath;
|
81 |
|
82 | var closestPackage = getClosestPackage(module.resource);
|
83 |
|
84 |
|
85 | if (!closestPackage) {
|
86 | return;
|
87 | }
|
88 |
|
89 | pkg = closestPackage.package;
|
90 | packagePath = closestPackage.path;
|
91 |
|
92 | var modulePath = cleanPathRelativeToContext(packagePath);
|
93 |
|
94 | var version = pkg.version;
|
95 |
|
96 | if (modulesToCheck.indexOf(pkg.name) < 0) {
|
97 | return;
|
98 | }
|
99 |
|
100 | modules[pkg.name] = modules[pkg.name] || [];
|
101 |
|
102 | var isSeen = false;
|
103 |
|
104 | modules[pkg.name].forEach(function (module) {
|
105 | if (module.version === version) {
|
106 | isSeen = true;
|
107 | }
|
108 | });
|
109 |
|
110 | if (!isSeen) {
|
111 | var entry = { version: version, path: modulePath };
|
112 |
|
113 | modules[pkg.name].push(entry);
|
114 | }
|
115 | });
|
116 |
|
117 | var duplicates = {};
|
118 | Object.keys(modules).forEach(function (name) {
|
119 | if (modules[name].length > 1) {
|
120 | duplicates[name] = modules[name];
|
121 | }
|
122 | });
|
123 |
|
124 | return duplicates;
|
125 | }
|
126 |
|
127 | function formatMsg(duplicates) {
|
128 | var error = 'Duplicate (conflicting) packages loaded, make sure to use only one: ';
|
129 |
|
130 | if (Object.keys(duplicates).length) {
|
131 | Object.keys(duplicates).forEach(function (key) {
|
132 | var instances = duplicates[key];
|
133 | instances = instances.map(function (version) {
|
134 | var str = version.version + ' ' + version.path;
|
135 | return str;
|
136 | });
|
137 | error += '\\n <' + key + '> \\n';
|
138 | error += ' ' + instances.join('\\n ') + '\\n';
|
139 | });
|
140 | }
|
141 |
|
142 | return error;
|
143 | }
|
144 |
|
145 | var DuplicateChecker = function () {
|
146 | function DuplicateChecker(options) {
|
147 | _classCallCheck(this, DuplicateChecker);
|
148 |
|
149 | this.options = Object.assign({}, options);;
|
150 | }
|
151 |
|
152 | _createClass(DuplicateChecker, [{
|
153 | key: 'apply',
|
154 | value: function apply(compiler) {
|
155 | var modulesToCheck = this.options.modulesToCheck;
|
156 | if (!modulesToCheck || !modulesToCheck.length) {
|
157 | return;
|
158 | }
|
159 |
|
160 | compiler.plugin('compilation', function (compilation) {
|
161 | compilation.plugin('optimize-chunk-assets', function (chunks, callback) {
|
162 | chunks.forEach(function (chunk) {
|
163 |
|
164 | try {
|
165 | if (!chunk.initial) return;
|
166 | } catch (e) {
|
167 | if (!chunk.isInitial()) return;
|
168 | }
|
169 |
|
170 | var duplicates = check(compilation, modulesToCheck);
|
171 |
|
172 | if (Object.keys(duplicates).length && !isProducation) {
|
173 | var errorMessages = formatMsg(duplicates);
|
174 | chunk.files.forEach(function (file) {
|
175 | compilation.assets[file] = new ConcatSource(compilation.assets[file], '\n console.error(\'' + errorMessages + '\');');
|
176 | });
|
177 | }
|
178 | });
|
179 | callback();
|
180 | });
|
181 | });
|
182 | }
|
183 | }]);
|
184 |
|
185 | return DuplicateChecker;
|
186 | }();
|
187 |
|
188 | exports.default = DuplicateChecker;
|
189 | module.exports = exports['default']; |
\ | No newline at end of file |