1
|
/*
|
2
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
Author Tobias Koppers @sokra
|
4
|
*/
|
5
|
"use strict";
|
6
|
|
7
|
const RequestShortener = require("./RequestShortener");
|
8
|
const SizeFormatHelpers = require("./SizeFormatHelpers");
|
9
|
const formatLocation = require("./formatLocation");
|
10
|
const identifierUtils = require("./util/identifier");
|
11
|
const compareLocations = require("./compareLocations");
|
12
|
const { LogType } = require("./logging/Logger");
|
13
|
|
14
|
const optionsOrFallback = (...args) => {
|
15
|
let optionValues = [];
|
16
|
optionValues.push(...args);
|
17
|
return optionValues.find(optionValue => optionValue !== undefined);
|
18
|
};
|
19
|
|
20
|
const compareId = (a, b) => {
|
21
|
if (typeof a !== typeof b) {
|
22
|
return typeof a < typeof b ? -1 : 1;
|
23
|
}
|
24
|
if (a < b) return -1;
|
25
|
if (a > b) return 1;
|
26
|
return 0;
|
27
|
};
|
28
|
|
29
|
class Stats {
|
30
|
constructor(compilation) {
|
31
|
this.compilation = compilation;
|
32
|
this.hash = compilation.hash;
|
33
|
this.startTime = undefined;
|
34
|
this.endTime = undefined;
|
35
|
}
|
36
|
|
37
|
static filterWarnings(warnings, warningsFilter) {
|
38
|
// we dont have anything to filter so all warnings can be shown
|
39
|
if (!warningsFilter) {
|
40
|
return warnings;
|
41
|
}
|
42
|
|
43
|
// create a chain of filters
|
44
|
// if they return "true" a warning should be suppressed
|
45
|
const normalizedWarningsFilters = [].concat(warningsFilter).map(filter => {
|
46
|
if (typeof filter === "string") {
|
47
|
return warning => warning.includes(filter);
|
48
|
}
|
49
|
|
50
|
if (filter instanceof RegExp) {
|
51
|
return warning => filter.test(warning);
|
52
|
}
|
53
|
|
54
|
if (typeof filter === "function") {
|
55
|
return filter;
|
56
|
}
|
57
|
|
58
|
throw new Error(
|
59
|
`Can only filter warnings with Strings or RegExps. (Given: ${filter})`
|
60
|
);
|
61
|
});
|
62
|
return warnings.filter(warning => {
|
63
|
return !normalizedWarningsFilters.some(check => check(warning));
|
64
|
});
|
65
|
}
|
66
|
|
67
|
formatFilePath(filePath) {
|
68
|
const OPTIONS_REGEXP = /^(\s|\S)*!/;
|
69
|
return filePath.includes("!")
|
70
|
? `${filePath.replace(OPTIONS_REGEXP, "")} (${filePath})`
|
71
|
: `${filePath}`;
|
72
|
}
|
73
|
|
74
|
hasWarnings() {
|
75
|
return (
|
76
|
this.compilation.warnings.length > 0 ||
|
77
|
this.compilation.children.some(child => child.getStats().hasWarnings())
|
78
|
);
|
79
|
}
|
80
|
|
81
|
hasErrors() {
|
82
|
return (
|
83
|
this.compilation.errors.length > 0 ||
|
84
|
this.compilation.children.some(child => child.getStats().hasErrors())
|
85
|
);
|
86
|
}
|
87
|
|
88
|
// remove a prefixed "!" that can be specified to reverse sort order
|
89
|
normalizeFieldKey(field) {
|
90
|
if (field[0] === "!") {
|
91
|
return field.substr(1);
|
92
|
}
|
93
|
return field;
|
94
|
}
|
95
|
|
96
|
// if a field is prefixed by a "!" reverse sort order
|
97
|
sortOrderRegular(field) {
|
98
|
if (field[0] === "!") {
|
99
|
return false;
|
100
|
}
|
101
|
return true;
|
102
|
}
|
103
|
|
104
|
toJson(options, forToString) {
|
105
|
if (typeof options === "boolean" || typeof options === "string") {
|
106
|
options = Stats.presetToOptions(options);
|
107
|
} else if (!options) {
|
108
|
options = {};
|
109
|
}
|
110
|
|
111
|
const optionOrLocalFallback = (v, def) =>
|
112
|
v !== undefined ? v : options.all !== undefined ? options.all : def;
|
113
|
|
114
|
const testAgainstGivenOption = item => {
|
115
|
if (typeof item === "string") {
|
116
|
const regExp = new RegExp(
|
117
|
`[\\\\/]${item.replace(
|
118
|
// eslint-disable-next-line no-useless-escape
|
119
|
/[-[\]{}()*+?.\\^$|]/g,
|
120
|
"\\$&"
|
121
|
)}([\\\\/]|$|!|\\?)`
|
122
|
);
|
123
|
return ident => regExp.test(ident);
|
124
|
}
|
125
|
if (item && typeof item === "object" && typeof item.test === "function") {
|
126
|
return ident => item.test(ident);
|
127
|
}
|
128
|
if (typeof item === "function") {
|
129
|
return item;
|
130
|
}
|
131
|
if (typeof item === "boolean") {
|
132
|
return () => item;
|
133
|
}
|
134
|
};
|
135
|
|
136
|
const compilation = this.compilation;
|
137
|
const context = optionsOrFallback(
|
138
|
options.context,
|
139
|
compilation.compiler.context
|
140
|
);
|
141
|
const requestShortener =
|
142
|
compilation.compiler.context === context
|
143
|
? compilation.requestShortener
|
144
|
: new RequestShortener(context);
|
145
|
const showPerformance = optionOrLocalFallback(options.performance, true);
|
146
|
const showHash = optionOrLocalFallback(options.hash, true);
|
147
|
const showEnv = optionOrLocalFallback(options.env, false);
|
148
|
const showVersion = optionOrLocalFallback(options.version, true);
|
149
|
const showTimings = optionOrLocalFallback(options.timings, true);
|
150
|
const showBuiltAt = optionOrLocalFallback(options.builtAt, true);
|
151
|
const showAssets = optionOrLocalFallback(options.assets, true);
|
152
|
const showEntrypoints = optionOrLocalFallback(options.entrypoints, true);
|
153
|
const showChunkGroups = optionOrLocalFallback(
|
154
|
options.chunkGroups,
|
155
|
!forToString
|
156
|
);
|
157
|
const showChunks = optionOrLocalFallback(options.chunks, !forToString);
|
158
|
const showChunkModules = optionOrLocalFallback(options.chunkModules, true);
|
159
|
const showChunkOrigins = optionOrLocalFallback(
|
160
|
options.chunkOrigins,
|
161
|
!forToString
|
162
|
);
|
163
|
const showModules = optionOrLocalFallback(options.modules, true);
|
164
|
const showNestedModules = optionOrLocalFallback(
|
165
|
options.nestedModules,
|
166
|
true
|
167
|
);
|
168
|
const showModuleAssets = optionOrLocalFallback(
|
169
|
options.moduleAssets,
|
170
|
!forToString
|
171
|
);
|
172
|
const showDepth = optionOrLocalFallback(options.depth, !forToString);
|
173
|
const showCachedModules = optionOrLocalFallback(options.cached, true);
|
174
|
const showCachedAssets = optionOrLocalFallback(options.cachedAssets, true);
|
175
|
const showReasons = optionOrLocalFallback(options.reasons, !forToString);
|
176
|
const showUsedExports = optionOrLocalFallback(
|
177
|
options.usedExports,
|
178
|
!forToString
|
179
|
);
|
180
|
const showProvidedExports = optionOrLocalFallback(
|
181
|
options.providedExports,
|
182
|
!forToString
|
183
|
);
|
184
|
const showOptimizationBailout = optionOrLocalFallback(
|
185
|
options.optimizationBailout,
|
186
|
!forToString
|
187
|
);
|
188
|
const showChildren = optionOrLocalFallback(options.children, true);
|
189
|
const showSource = optionOrLocalFallback(options.source, !forToString);
|
190
|
const showModuleTrace = optionOrLocalFallback(options.moduleTrace, true);
|
191
|
const showErrors = optionOrLocalFallback(options.errors, true);
|
192
|
const showErrorDetails = optionOrLocalFallback(
|
193
|
options.errorDetails,
|
194
|
!forToString
|
195
|
);
|
196
|
const showWarnings = optionOrLocalFallback(options.warnings, true);
|
197
|
const warningsFilter = optionsOrFallback(options.warningsFilter, null);
|
198
|
const showPublicPath = optionOrLocalFallback(
|
199
|
options.publicPath,
|
200
|
!forToString
|
201
|
);
|
202
|
const showLogging = optionOrLocalFallback(
|
203
|
options.logging,
|
204
|
forToString ? "info" : true
|
205
|
);
|
206
|
const showLoggingTrace = optionOrLocalFallback(
|
207
|
options.loggingTrace,
|
208
|
!forToString
|
209
|
);
|
210
|
const loggingDebug = []
|
211
|
.concat(optionsOrFallback(options.loggingDebug, []))
|
212
|
.map(testAgainstGivenOption);
|
213
|
|
214
|
const excludeModules = []
|
215
|
.concat(optionsOrFallback(options.excludeModules, options.exclude, []))
|
216
|
.map(testAgainstGivenOption);
|
217
|
const excludeAssets = []
|
218
|
.concat(optionsOrFallback(options.excludeAssets, []))
|
219
|
.map(testAgainstGivenOption);
|
220
|
const maxModules = optionsOrFallback(
|
221
|
options.maxModules,
|
222
|
forToString ? 15 : Infinity
|
223
|
);
|
224
|
const sortModules = optionsOrFallback(options.modulesSort, "id");
|
225
|
const sortChunks = optionsOrFallback(options.chunksSort, "id");
|
226
|
const sortAssets = optionsOrFallback(options.assetsSort, "");
|
227
|
const showOutputPath = optionOrLocalFallback(
|
228
|
options.outputPath,
|
229
|
!forToString
|
230
|
);
|
231
|
|
232
|
if (!showCachedModules) {
|
233
|
excludeModules.push((ident, module) => !module.built);
|
234
|
}
|
235
|
|
236
|
const createModuleFilter = () => {
|
237
|
let i = 0;
|
238
|
return module => {
|
239
|
if (excludeModules.length > 0) {
|
240
|
const ident = requestShortener.shorten(module.resource);
|
241
|
const excluded = excludeModules.some(fn => fn(ident, module));
|
242
|
if (excluded) return false;
|
243
|
}
|
244
|
const result = i < maxModules;
|
245
|
i++;
|
246
|
return result;
|
247
|
};
|
248
|
};
|
249
|
|
250
|
const createAssetFilter = () => {
|
251
|
return asset => {
|
252
|
if (excludeAssets.length > 0) {
|
253
|
const ident = asset.name;
|
254
|
const excluded = excludeAssets.some(fn => fn(ident, asset));
|
255
|
if (excluded) return false;
|
256
|
}
|
257
|
return showCachedAssets || asset.emitted;
|
258
|
};
|
259
|
};
|
260
|
|
261
|
const sortByFieldAndOrder = (fieldKey, a, b) => {
|
262
|
if (a[fieldKey] === null && b[fieldKey] === null) return 0;
|
263
|
if (a[fieldKey] === null) return 1;
|
264
|
if (b[fieldKey] === null) return -1;
|
265
|
if (a[fieldKey] === b[fieldKey]) return 0;
|
266
|
if (typeof a[fieldKey] !== typeof b[fieldKey])
|
267
|
return typeof a[fieldKey] < typeof b[fieldKey] ? -1 : 1;
|
268
|
return a[fieldKey] < b[fieldKey] ? -1 : 1;
|
269
|
};
|
270
|
|
271
|
const sortByField = (field, originalArray) => {
|
272
|
const originalMap = originalArray.reduce((map, v, i) => {
|
273
|
map.set(v, i);
|
274
|
return map;
|
275
|
}, new Map());
|
276
|
return (a, b) => {
|
277
|
if (field) {
|
278
|
const fieldKey = this.normalizeFieldKey(field);
|
279
|
|
280
|
// if a field is prefixed with a "!" the sort is reversed!
|
281
|
const sortIsRegular = this.sortOrderRegular(field);
|
282
|
|
283
|
const cmp = sortByFieldAndOrder(
|
284
|
fieldKey,
|
285
|
sortIsRegular ? a : b,
|
286
|
sortIsRegular ? b : a
|
287
|
);
|
288
|
if (cmp) return cmp;
|
289
|
}
|
290
|
return originalMap.get(a) - originalMap.get(b);
|
291
|
};
|
292
|
};
|
293
|
|
294
|
const formatError = e => {
|
295
|
let text = "";
|
296
|
if (typeof e === "string") {
|
297
|
e = { message: e };
|
298
|
}
|
299
|
if (e.chunk) {
|
300
|
text += `chunk ${e.chunk.name || e.chunk.id}${
|
301
|
e.chunk.hasRuntime()
|
302
|
? " [entry]"
|
303
|
: e.chunk.canBeInitial()
|
304
|
? " [initial]"
|
305
|
: ""
|
306
|
}\n`;
|
307
|
}
|
308
|
if (e.file) {
|
309
|
text += `${e.file}\n`;
|
310
|
}
|
311
|
if (
|
312
|
e.module &&
|
313
|
e.module.readableIdentifier &&
|
314
|
typeof e.module.readableIdentifier === "function"
|
315
|
) {
|
316
|
text += this.formatFilePath(
|
317
|
e.module.readableIdentifier(requestShortener)
|
318
|
);
|
319
|
if (typeof e.loc === "object") {
|
320
|
const locInfo = formatLocation(e.loc);
|
321
|
if (locInfo) text += ` ${locInfo}`;
|
322
|
}
|
323
|
text += "\n";
|
324
|
}
|
325
|
text += e.message;
|
326
|
if (showErrorDetails && e.details) {
|
327
|
text += `\n${e.details}`;
|
328
|
}
|
329
|
if (showErrorDetails && e.missing) {
|
330
|
text += e.missing.map(item => `\n[${item}]`).join("");
|
331
|
}
|
332
|
if (showModuleTrace && e.origin) {
|
333
|
text += `\n @ ${this.formatFilePath(
|
334
|
e.origin.readableIdentifier(requestShortener)
|
335
|
)}`;
|
336
|
if (typeof e.originLoc === "object") {
|
337
|
const locInfo = formatLocation(e.originLoc);
|
338
|
if (locInfo) text += ` ${locInfo}`;
|
339
|
}
|
340
|
if (e.dependencies) {
|
341
|
for (const dep of e.dependencies) {
|
342
|
if (!dep.loc) continue;
|
343
|
if (typeof dep.loc === "string") continue;
|
344
|
const locInfo = formatLocation(dep.loc);
|
345
|
if (!locInfo) continue;
|
346
|
text += ` ${locInfo}`;
|
347
|
}
|
348
|
}
|
349
|
let current = e.origin;
|
350
|
while (current.issuer) {
|
351
|
current = current.issuer;
|
352
|
text += `\n @ ${current.readableIdentifier(requestShortener)}`;
|
353
|
}
|
354
|
}
|
355
|
return text;
|
356
|
};
|
357
|
|
358
|
const obj = {
|
359
|
errors: compilation.errors.map(formatError),
|
360
|
warnings: Stats.filterWarnings(
|
361
|
compilation.warnings.map(formatError),
|
362
|
warningsFilter
|
363
|
)
|
364
|
};
|
365
|
|
366
|
//We just hint other renderers since actually omitting
|
367
|
//errors/warnings from the JSON would be kind of weird.
|
368
|
Object.defineProperty(obj, "_showWarnings", {
|
369
|
value: showWarnings,
|
370
|
enumerable: false
|
371
|
});
|
372
|
Object.defineProperty(obj, "_showErrors", {
|
373
|
value: showErrors,
|
374
|
enumerable: false
|
375
|
});
|
376
|
|
377
|
if (showVersion) {
|
378
|
obj.version = require("../package.json").version;
|
379
|
}
|
380
|
|
381
|
if (showHash) obj.hash = this.hash;
|
382
|
if (showTimings && this.startTime && this.endTime) {
|
383
|
obj.time = this.endTime - this.startTime;
|
384
|
}
|
385
|
|
386
|
if (showBuiltAt && this.endTime) {
|
387
|
obj.builtAt = this.endTime;
|
388
|
}
|
389
|
|
390
|
if (showEnv && options._env) {
|
391
|
obj.env = options._env;
|
392
|
}
|
393
|
|
394
|
if (compilation.needAdditionalPass) {
|
395
|
obj.needAdditionalPass = true;
|
396
|
}
|
397
|
if (showPublicPath) {
|
398
|
obj.publicPath = this.compilation.mainTemplate.getPublicPath({
|
399
|
hash: this.compilation.hash
|
400
|
});
|
401
|
}
|
402
|
if (showOutputPath) {
|
403
|
obj.outputPath = this.compilation.mainTemplate.outputOptions.path;
|
404
|
}
|
405
|
if (showAssets) {
|
406
|
const assetsByFile = {};
|
407
|
const compilationAssets = compilation
|
408
|
.getAssets()
|
409
|
.sort((a, b) => (a.name < b.name ? -1 : 1));
|
410
|
obj.assetsByChunkName = {};
|
411
|
obj.assets = compilationAssets
|
412
|
.map(({ name, source, info }) => {
|
413
|
const obj = {
|
414
|
name,
|
415
|
size: source.size(),
|
416
|
chunks: [],
|
417
|
chunkNames: [],
|
418
|
info,
|
419
|
// TODO webpack 5: remove .emitted
|
420
|
emitted: source.emitted || compilation.emittedAssets.has(name)
|
421
|
};
|
422
|
|
423
|
if (showPerformance) {
|
424
|
obj.isOverSizeLimit = source.isOverSizeLimit;
|
425
|
}
|
426
|
|
427
|
assetsByFile[name] = obj;
|
428
|
return obj;
|
429
|
})
|
430
|
.filter(createAssetFilter());
|
431
|
obj.filteredAssets = compilationAssets.length - obj.assets.length;
|
432
|
|
433
|
for (const chunk of compilation.chunks) {
|
434
|
for (const asset of chunk.files) {
|
435
|
if (assetsByFile[asset]) {
|
436
|
for (const id of chunk.ids) {
|
437
|
assetsByFile[asset].chunks.push(id);
|
438
|
}
|
439
|
if (chunk.name) {
|
440
|
assetsByFile[asset].chunkNames.push(chunk.name);
|
441
|
if (obj.assetsByChunkName[chunk.name]) {
|
442
|
obj.assetsByChunkName[chunk.name] = []
|
443
|
.concat(obj.assetsByChunkName[chunk.name])
|
444
|
.concat([asset]);
|
445
|
} else {
|
446
|
obj.assetsByChunkName[chunk.name] = asset;
|
447
|
}
|
448
|
}
|
449
|
}
|
450
|
}
|
451
|
}
|
452
|
obj.assets.sort(sortByField(sortAssets, obj.assets));
|
453
|
}
|
454
|
|
455
|
const fnChunkGroup = groupMap => {
|
456
|
const obj = {};
|
457
|
for (const keyValuePair of groupMap) {
|
458
|
const name = keyValuePair[0];
|
459
|
const cg = keyValuePair[1];
|
460
|
const children = cg.getChildrenByOrders();
|
461
|
obj[name] = {
|
462
|
chunks: cg.chunks.map(c => c.id),
|
463
|
assets: cg.chunks.reduce(
|
464
|
(array, c) => array.concat(c.files || []),
|
465
|
[]
|
466
|
),
|
467
|
children: Object.keys(children).reduce((obj, key) => {
|
468
|
const groups = children[key];
|
469
|
obj[key] = groups.map(group => ({
|
470
|
name: group.name,
|
471
|
chunks: group.chunks.map(c => c.id),
|
472
|
assets: group.chunks.reduce(
|
473
|
(array, c) => array.concat(c.files || []),
|
474
|
[]
|
475
|
)
|
476
|
}));
|
477
|
return obj;
|
478
|
}, Object.create(null)),
|
479
|
childAssets: Object.keys(children).reduce((obj, key) => {
|
480
|
const groups = children[key];
|
481
|
obj[key] = Array.from(
|
482
|
groups.reduce((set, group) => {
|
483
|
for (const chunk of group.chunks) {
|
484
|
for (const asset of chunk.files) {
|
485
|
set.add(asset);
|
486
|
}
|
487
|
}
|
488
|
return set;
|
489
|
}, new Set())
|
490
|
);
|
491
|
return obj;
|
492
|
}, Object.create(null))
|
493
|
};
|
494
|
if (showPerformance) {
|
495
|
obj[name].isOverSizeLimit = cg.isOverSizeLimit;
|
496
|
}
|
497
|
}
|
498
|
|
499
|
return obj;
|
500
|
};
|
501
|
|
502
|
if (showEntrypoints) {
|
503
|
obj.entrypoints = fnChunkGroup(compilation.entrypoints);
|
504
|
}
|
505
|
|
506
|
if (showChunkGroups) {
|
507
|
obj.namedChunkGroups = fnChunkGroup(compilation.namedChunkGroups);
|
508
|
}
|
509
|
|
510
|
const fnModule = module => {
|
511
|
const path = [];
|
512
|
let current = module;
|
513
|
while (current.issuer) {
|
514
|
path.push((current = current.issuer));
|
515
|
}
|
516
|
path.reverse();
|
517
|
const obj = {
|
518
|
id: module.id,
|
519
|
identifier: module.identifier(),
|
520
|
name: module.readableIdentifier(requestShortener),
|
521
|
index: module.index,
|
522
|
index2: module.index2,
|
523
|
size: module.size(),
|
524
|
cacheable: module.buildInfo.cacheable,
|
525
|
built: !!module.built,
|
526
|
optional: module.optional,
|
527
|
prefetched: module.prefetched,
|
528
|
chunks: Array.from(module.chunksIterable, chunk => chunk.id),
|
529
|
issuer: module.issuer && module.issuer.identifier(),
|
530
|
issuerId: module.issuer && module.issuer.id,
|
531
|
issuerName:
|
532
|
module.issuer && module.issuer.readableIdentifier(requestShortener),
|
533
|
issuerPath:
|
534
|
module.issuer &&
|
535
|
path.map(module => ({
|
536
|
id: module.id,
|
537
|
identifier: module.identifier(),
|
538
|
name: module.readableIdentifier(requestShortener),
|
539
|
profile: module.profile
|
540
|
})),
|
541
|
profile: module.profile,
|
542
|
failed: !!module.error,
|
543
|
errors: module.errors ? module.errors.length : 0,
|
544
|
warnings: module.warnings ? module.warnings.length : 0
|
545
|
};
|
546
|
if (showModuleAssets) {
|
547
|
obj.assets = Object.keys(module.buildInfo.assets || {});
|
548
|
}
|
549
|
if (showReasons) {
|
550
|
obj.reasons = module.reasons
|
551
|
.sort((a, b) => {
|
552
|
if (a.module && !b.module) return -1;
|
553
|
if (!a.module && b.module) return 1;
|
554
|
if (a.module && b.module) {
|
555
|
const cmp = compareId(a.module.id, b.module.id);
|
556
|
if (cmp) return cmp;
|
557
|
}
|
558
|
if (a.dependency && !b.dependency) return -1;
|
559
|
if (!a.dependency && b.dependency) return 1;
|
560
|
if (a.dependency && b.dependency) {
|
561
|
const cmp = compareLocations(a.dependency.loc, b.dependency.loc);
|
562
|
if (cmp) return cmp;
|
563
|
if (a.dependency.type < b.dependency.type) return -1;
|
564
|
if (a.dependency.type > b.dependency.type) return 1;
|
565
|
}
|
566
|
return 0;
|
567
|
})
|
568
|
.map(reason => {
|
569
|
const obj = {
|
570
|
moduleId: reason.module ? reason.module.id : null,
|
571
|
moduleIdentifier: reason.module
|
572
|
? reason.module.identifier()
|
573
|
: null,
|
574
|
module: reason.module
|
575
|
? reason.module.readableIdentifier(requestShortener)
|
576
|
: null,
|
577
|
moduleName: reason.module
|
578
|
? reason.module.readableIdentifier(requestShortener)
|
579
|
: null,
|
580
|
type: reason.dependency ? reason.dependency.type : null,
|
581
|
explanation: reason.explanation,
|
582
|
userRequest: reason.dependency
|
583
|
? reason.dependency.userRequest
|
584
|
: null
|
585
|
};
|
586
|
if (reason.dependency) {
|
587
|
const locInfo = formatLocation(reason.dependency.loc);
|
588
|
if (locInfo) {
|
589
|
obj.loc = locInfo;
|
590
|
}
|
591
|
}
|
592
|
return obj;
|
593
|
});
|
594
|
}
|
595
|
if (showUsedExports) {
|
596
|
if (module.used === true) {
|
597
|
obj.usedExports = module.usedExports;
|
598
|
} else if (module.used === false) {
|
599
|
obj.usedExports = false;
|
600
|
}
|
601
|
}
|
602
|
if (showProvidedExports) {
|
603
|
obj.providedExports = Array.isArray(module.buildMeta.providedExports)
|
604
|
? module.buildMeta.providedExports
|
605
|
: null;
|
606
|
}
|
607
|
if (showOptimizationBailout) {
|
608
|
obj.optimizationBailout = module.optimizationBailout.map(item => {
|
609
|
if (typeof item === "function") return item(requestShortener);
|
610
|
return item;
|
611
|
});
|
612
|
}
|
613
|
if (showDepth) {
|
614
|
obj.depth = module.depth;
|
615
|
}
|
616
|
if (showNestedModules) {
|
617
|
if (module.modules) {
|
618
|
const modules = module.modules;
|
619
|
obj.modules = modules
|
620
|
.sort(sortByField("depth", modules))
|
621
|
.filter(createModuleFilter())
|
622
|
.map(fnModule);
|
623
|
obj.filteredModules = modules.length - obj.modules.length;
|
624
|
obj.modules.sort(sortByField(sortModules, obj.modules));
|
625
|
}
|
626
|
}
|
627
|
if (showSource && module._source) {
|
628
|
obj.source = module._source.source();
|
629
|
}
|
630
|
return obj;
|
631
|
};
|
632
|
if (showChunks) {
|
633
|
obj.chunks = compilation.chunks.map(chunk => {
|
634
|
const parents = new Set();
|
635
|
const children = new Set();
|
636
|
const siblings = new Set();
|
637
|
const childIdByOrder = chunk.getChildIdsByOrders();
|
638
|
for (const chunkGroup of chunk.groupsIterable) {
|
639
|
for (const parentGroup of chunkGroup.parentsIterable) {
|
640
|
for (const chunk of parentGroup.chunks) {
|
641
|
parents.add(chunk.id);
|
642
|
}
|
643
|
}
|
644
|
for (const childGroup of chunkGroup.childrenIterable) {
|
645
|
for (const chunk of childGroup.chunks) {
|
646
|
children.add(chunk.id);
|
647
|
}
|
648
|
}
|
649
|
for (const sibling of chunkGroup.chunks) {
|
650
|
if (sibling !== chunk) siblings.add(sibling.id);
|
651
|
}
|
652
|
}
|
653
|
const obj = {
|
654
|
id: chunk.id,
|
655
|
rendered: chunk.rendered,
|
656
|
initial: chunk.canBeInitial(),
|
657
|
entry: chunk.hasRuntime(),
|
658
|
recorded: chunk.recorded,
|
659
|
reason: chunk.chunkReason,
|
660
|
size: chunk.modulesSize(),
|
661
|
names: chunk.name ? [chunk.name] : [],
|
662
|
files: chunk.files.slice(),
|
663
|
hash: chunk.renderedHash,
|
664
|
siblings: Array.from(siblings).sort(compareId),
|
665
|
parents: Array.from(parents).sort(compareId),
|
666
|
children: Array.from(children).sort(compareId),
|
667
|
childrenByOrder: childIdByOrder
|
668
|
};
|
669
|
if (showChunkModules) {
|
670
|
const modules = chunk.getModules();
|
671
|
obj.modules = modules
|
672
|
.slice()
|
673
|
.sort(sortByField("depth", modules))
|
674
|
.filter(createModuleFilter())
|
675
|
.map(fnModule);
|
676
|
obj.filteredModules = chunk.getNumberOfModules() - obj.modules.length;
|
677
|
obj.modules.sort(sortByField(sortModules, obj.modules));
|
678
|
}
|
679
|
if (showChunkOrigins) {
|
680
|
obj.origins = Array.from(chunk.groupsIterable, g => g.origins)
|
681
|
.reduce((a, b) => a.concat(b), [])
|
682
|
.map(origin => ({
|
683
|
moduleId: origin.module ? origin.module.id : undefined,
|
684
|
module: origin.module ? origin.module.identifier() : "",
|
685
|
moduleIdentifier: origin.module ? origin.module.identifier() : "",
|
686
|
moduleName: origin.module
|
687
|
? origin.module.readableIdentifier(requestShortener)
|
688
|
: "",
|
689
|
loc: formatLocation(origin.loc),
|
690
|
request: origin.request,
|
691
|
reasons: origin.reasons || []
|
692
|
}))
|
693
|
.sort((a, b) => {
|
694
|
const cmp1 = compareId(a.moduleId, b.moduleId);
|
695
|
if (cmp1) return cmp1;
|
696
|
const cmp2 = compareId(a.loc, b.loc);
|
697
|
if (cmp2) return cmp2;
|
698
|
const cmp3 = compareId(a.request, b.request);
|
699
|
if (cmp3) return cmp3;
|
700
|
return 0;
|
701
|
});
|
702
|
}
|
703
|
return obj;
|
704
|
});
|
705
|
obj.chunks.sort(sortByField(sortChunks, obj.chunks));
|
706
|
}
|
707
|
if (showModules) {
|
708
|
obj.modules = compilation.modules
|
709
|
.slice()
|
710
|
.sort(sortByField("depth", compilation.modules))
|
711
|
.filter(createModuleFilter())
|
712
|
.map(fnModule);
|
713
|
obj.filteredModules = compilation.modules.length - obj.modules.length;
|
714
|
obj.modules.sort(sortByField(sortModules, obj.modules));
|
715
|
}
|
716
|
if (showLogging) {
|
717
|
const util = require("util");
|
718
|
obj.logging = {};
|
719
|
let acceptedTypes;
|
720
|
let collapsedGroups = false;
|
721
|
switch (showLogging) {
|
722
|
case "none":
|
723
|
acceptedTypes = new Set([]);
|
724
|
break;
|
725
|
case "error":
|
726
|
acceptedTypes = new Set([LogType.error]);
|
727
|
break;
|
728
|
case "warn":
|
729
|
acceptedTypes = new Set([LogType.error, LogType.warn]);
|
730
|
break;
|
731
|
case "info":
|
732
|
acceptedTypes = new Set([LogType.error, LogType.warn, LogType.info]);
|
733
|
break;
|
734
|
case true:
|
735
|
case "log":
|
736
|
acceptedTypes = new Set([
|
737
|
LogType.error,
|
738
|
LogType.warn,
|
739
|
LogType.info,
|
740
|
LogType.log,
|
741
|
LogType.group,
|
742
|
LogType.groupEnd,
|
743
|
LogType.groupCollapsed,
|
744
|
LogType.clear
|
745
|
]);
|
746
|
break;
|
747
|
case "verbose":
|
748
|
acceptedTypes = new Set([
|
749
|
LogType.error,
|
750
|
LogType.warn,
|
751
|
LogType.info,
|
752
|
LogType.log,
|
753
|
LogType.group,
|
754
|
LogType.groupEnd,
|
755
|
LogType.groupCollapsed,
|
756
|
LogType.profile,
|
757
|
LogType.profileEnd,
|
758
|
LogType.time,
|
759
|
LogType.status,
|
760
|
LogType.clear
|
761
|
]);
|
762
|
collapsedGroups = true;
|
763
|
break;
|
764
|
}
|
765
|
for (const [origin, logEntries] of compilation.logging) {
|
766
|
const debugMode = loggingDebug.some(fn => fn(origin));
|
767
|
let collapseCounter = 0;
|
768
|
let processedLogEntries = logEntries;
|
769
|
if (!debugMode) {
|
770
|
processedLogEntries = processedLogEntries.filter(entry => {
|
771
|
if (!acceptedTypes.has(entry.type)) return false;
|
772
|
if (!collapsedGroups) {
|
773
|
switch (entry.type) {
|
774
|
case LogType.groupCollapsed:
|
775
|
collapseCounter++;
|
776
|
return collapseCounter === 1;
|
777
|
case LogType.group:
|
778
|
if (collapseCounter > 0) collapseCounter++;
|
779
|
return collapseCounter === 0;
|
780
|
case LogType.groupEnd:
|
781
|
if (collapseCounter > 0) {
|
782
|
collapseCounter--;
|
783
|
return false;
|
784
|
}
|
785
|
return true;
|
786
|
default:
|
787
|
return collapseCounter === 0;
|
788
|
}
|
789
|
}
|
790
|
return true;
|
791
|
});
|
792
|
}
|
793
|
processedLogEntries = processedLogEntries.map(entry => {
|
794
|
let message = undefined;
|
795
|
if (entry.type === LogType.time) {
|
796
|
message = `${entry.args[0]}: ${entry.args[1] * 1000 +
|
797
|
entry.args[2] / 1000000}ms`;
|
798
|
} else if (entry.args && entry.args.length > 0) {
|
799
|
message = util.format(entry.args[0], ...entry.args.slice(1));
|
800
|
}
|
801
|
return {
|
802
|
type:
|
803
|
(debugMode || collapsedGroups) &&
|
804
|
entry.type === LogType.groupCollapsed
|
805
|
? LogType.group
|
806
|
: entry.type,
|
807
|
message,
|
808
|
trace: showLoggingTrace && entry.trace ? entry.trace : undefined
|
809
|
};
|
810
|
});
|
811
|
let name = identifierUtils
|
812
|
.makePathsRelative(context, origin, compilation.cache)
|
813
|
.replace(/\|/g, " ");
|
814
|
if (name in obj.logging) {
|
815
|
let i = 1;
|
816
|
while (`${name}#${i}` in obj.logging) {
|
817
|
i++;
|
818
|
}
|
819
|
name = `${name}#${i}`;
|
820
|
}
|
821
|
obj.logging[name] = {
|
822
|
entries: processedLogEntries,
|
823
|
filteredEntries: logEntries.length - processedLogEntries.length,
|
824
|
debug: debugMode
|
825
|
};
|
826
|
}
|
827
|
}
|
828
|
if (showChildren) {
|
829
|
obj.children = compilation.children.map((child, idx) => {
|
830
|
const childOptions = Stats.getChildOptions(options, idx);
|
831
|
const obj = new Stats(child).toJson(childOptions, forToString);
|
832
|
delete obj.hash;
|
833
|
delete obj.version;
|
834
|
if (child.name) {
|
835
|
obj.name = identifierUtils.makePathsRelative(
|
836
|
context,
|
837
|
child.name,
|
838
|
compilation.cache
|
839
|
);
|
840
|
}
|
841
|
return obj;
|
842
|
});
|
843
|
}
|
844
|
|
845
|
return obj;
|
846
|
}
|
847
|
|
848
|
toString(options) {
|
849
|
if (typeof options === "boolean" || typeof options === "string") {
|
850
|
options = Stats.presetToOptions(options);
|
851
|
} else if (!options) {
|
852
|
options = {};
|
853
|
}
|
854
|
|
855
|
const useColors = optionsOrFallback(options.colors, false);
|
856
|
|
857
|
const obj = this.toJson(options, true);
|
858
|
|
859
|
return Stats.jsonToString(obj, useColors);
|
860
|
}
|
861
|
|
862
|
static jsonToString(obj, useColors) {
|
863
|
const buf = [];
|
864
|
|
865
|
const defaultColors = {
|
866
|
bold: "\u001b[1m",
|
867
|
yellow: "\u001b[1m\u001b[33m",
|
868
|
red: "\u001b[1m\u001b[31m",
|
869
|
green: "\u001b[1m\u001b[32m",
|
870
|
cyan: "\u001b[1m\u001b[36m",
|
871
|
magenta: "\u001b[1m\u001b[35m"
|
872
|
};
|
873
|
|
874
|
const colors = Object.keys(defaultColors).reduce(
|
875
|
(obj, color) => {
|
876
|
obj[color] = str => {
|
877
|
if (useColors) {
|
878
|
buf.push(
|
879
|
useColors === true || useColors[color] === undefined
|
880
|
? defaultColors[color]
|
881
|
: useColors[color]
|
882
|
);
|
883
|
}
|
884
|
buf.push(str);
|
885
|
if (useColors) {
|
886
|
buf.push("\u001b[39m\u001b[22m");
|
887
|
}
|
888
|
};
|
889
|
return obj;
|
890
|
},
|
891
|
{
|
892
|
normal: str => buf.push(str)
|
893
|
}
|
894
|
);
|
895
|
|
896
|
const coloredTime = time => {
|
897
|
let times = [800, 400, 200, 100];
|
898
|
if (obj.time) {
|
899
|
times = [obj.time / 2, obj.time / 4, obj.time / 8, obj.time / 16];
|
900
|
}
|
901
|
if (time < times[3]) colors.normal(`${time}ms`);
|
902
|
else if (time < times[2]) colors.bold(`${time}ms`);
|
903
|
else if (time < times[1]) colors.green(`${time}ms`);
|
904
|
else if (time < times[0]) colors.yellow(`${time}ms`);
|
905
|
else colors.red(`${time}ms`);
|
906
|
};
|
907
|
|
908
|
const newline = () => buf.push("\n");
|
909
|
|
910
|
const getText = (arr, row, col) => {
|
911
|
return arr[row][col].value;
|
912
|
};
|
913
|
|
914
|
const table = (array, align, splitter) => {
|
915
|
const rows = array.length;
|
916
|
const cols = array[0].length;
|
917
|
const colSizes = new Array(cols);
|
918
|
for (let col = 0; col < cols; col++) {
|
919
|
colSizes[col] = 0;
|
920
|
}
|
921
|
for (let row = 0; row < rows; row++) {
|
922
|
for (let col = 0; col < cols; col++) {
|
923
|
const value = `${getText(array, row, col)}`;
|
924
|
if (value.length > colSizes[col]) {
|
925
|
colSizes[col] = value.length;
|
926
|
}
|
927
|
}
|
928
|
}
|
929
|
for (let row = 0; row < rows; row++) {
|
930
|
for (let col = 0; col < cols; col++) {
|
931
|
const format = array[row][col].color;
|
932
|
const value = `${getText(array, row, col)}`;
|
933
|
let l = value.length;
|
934
|
if (align[col] === "l") {
|
935
|
format(value);
|
936
|
}
|
937
|
for (; l < colSizes[col] && col !== cols - 1; l++) {
|
938
|
colors.normal(" ");
|
939
|
}
|
940
|
if (align[col] === "r") {
|
941
|
format(value);
|
942
|
}
|
943
|
if (col + 1 < cols && colSizes[col] !== 0) {
|
944
|
colors.normal(splitter || " ");
|
945
|
}
|
946
|
}
|
947
|
newline();
|
948
|
}
|
949
|
};
|
950
|
|
951
|
const getAssetColor = (asset, defaultColor) => {
|
952
|
if (asset.isOverSizeLimit) {
|
953
|
return colors.yellow;
|
954
|
}
|
955
|
|
956
|
return defaultColor;
|
957
|
};
|
958
|
|
959
|
if (obj.hash) {
|
960
|
colors.normal("Hash: ");
|
961
|
colors.bold(obj.hash);
|
962
|
newline();
|
963
|
}
|
964
|
if (obj.version) {
|
965
|
colors.normal("Version: webpack ");
|
966
|
colors.bold(obj.version);
|
967
|
newline();
|
968
|
}
|
969
|
if (typeof obj.time === "number") {
|
970
|
colors.normal("Time: ");
|
971
|
colors.bold(obj.time);
|
972
|
colors.normal("ms");
|
973
|
newline();
|
974
|
}
|
975
|
if (typeof obj.builtAt === "number") {
|
976
|
const builtAtDate = new Date(obj.builtAt);
|
977
|
let timeZone = undefined;
|
978
|
|
979
|
try {
|
980
|
builtAtDate.toLocaleTimeString();
|
981
|
} catch (err) {
|
982
|
// Force UTC if runtime timezone is unsupported
|
983
|
timeZone = "UTC";
|
984
|
}
|
985
|
|
986
|
colors.normal("Built at: ");
|
987
|
colors.normal(
|
988
|
builtAtDate.toLocaleDateString(undefined, {
|
989
|
day: "2-digit",
|
990
|
month: "2-digit",
|
991
|
year: "numeric",
|
992
|
timeZone
|
993
|
})
|
994
|
);
|
995
|
colors.normal(" ");
|
996
|
colors.bold(builtAtDate.toLocaleTimeString(undefined, { timeZone }));
|
997
|
newline();
|
998
|
}
|
999
|
if (obj.env) {
|
1000
|
colors.normal("Environment (--env): ");
|
1001
|
colors.bold(JSON.stringify(obj.env, null, 2));
|
1002
|
newline();
|
1003
|
}
|
1004
|
if (obj.publicPath) {
|
1005
|
colors.normal("PublicPath: ");
|
1006
|
colors.bold(obj.publicPath);
|
1007
|
newline();
|
1008
|
}
|
1009
|
|
1010
|
if (obj.assets && obj.assets.length > 0) {
|
1011
|
const t = [
|
1012
|
[
|
1013
|
{
|
1014
|
value: "Asset",
|
1015
|
color: colors.bold
|
1016
|
},
|
1017
|
{
|
1018
|
value: "Size",
|
1019
|
color: colors.bold
|
1020
|
},
|
1021
|
{
|
1022
|
value: "Chunks",
|
1023
|
color: colors.bold
|
1024
|
},
|
1025
|
{
|
1026
|
value: "",
|
1027
|
color: colors.bold
|
1028
|
},
|
1029
|
{
|
1030
|
value: "",
|
1031
|
color: colors.bold
|
1032
|
},
|
1033
|
{
|
1034
|
value: "Chunk Names",
|
1035
|
color: colors.bold
|
1036
|
}
|
1037
|
]
|
1038
|
];
|
1039
|
for (const asset of obj.assets) {
|
1040
|
t.push([
|
1041
|
{
|
1042
|
value: asset.name,
|
1043
|
color: getAssetColor(asset, colors.green)
|
1044
|
},
|
1045
|
{
|
1046
|
value: SizeFormatHelpers.formatSize(asset.size),
|
1047
|
color: getAssetColor(asset, colors.normal)
|
1048
|
},
|
1049
|
{
|
1050
|
value: asset.chunks.join(", "),
|
1051
|
color: colors.bold
|
1052
|
},
|
1053
|
{
|
1054
|
value: [
|
1055
|
asset.emitted && "[emitted]",
|
1056
|
asset.info.immutable && "[immutable]",
|
1057
|
asset.info.development && "[dev]",
|
1058
|
asset.info.hotModuleReplacement && "[hmr]"
|
1059
|
]
|
1060
|
.filter(Boolean)
|
1061
|
.join(" "),
|
1062
|
color: colors.green
|
1063
|
},
|
1064
|
{
|
1065
|
value: asset.isOverSizeLimit ? "[big]" : "",
|
1066
|
color: getAssetColor(asset, colors.normal)
|
1067
|
},
|
1068
|
{
|
1069
|
value: asset.chunkNames.join(", "),
|
1070
|
color: colors.normal
|
1071
|
}
|
1072
|
]);
|
1073
|
}
|
1074
|
table(t, "rrrlll");
|
1075
|
}
|
1076
|
if (obj.filteredAssets > 0) {
|
1077
|
colors.normal(" ");
|
1078
|
if (obj.assets.length > 0) colors.normal("+ ");
|
1079
|
colors.normal(obj.filteredAssets);
|
1080
|
if (obj.assets.length > 0) colors.normal(" hidden");
|
1081
|
colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset");
|
1082
|
newline();
|
1083
|
}
|
1084
|
|
1085
|
const processChunkGroups = (namedGroups, prefix) => {
|
1086
|
for (const name of Object.keys(namedGroups)) {
|
1087
|
const cg = namedGroups[name];
|
1088
|
colors.normal(`${prefix} `);
|
1089
|
colors.bold(name);
|
1090
|
if (cg.isOverSizeLimit) {
|
1091
|
colors.normal(" ");
|
1092
|
colors.yellow("[big]");
|
1093
|
}
|
1094
|
colors.normal(" =");
|
1095
|
for (const asset of cg.assets) {
|
1096
|
colors.normal(" ");
|
1097
|
colors.green(asset);
|
1098
|
}
|
1099
|
for (const name of Object.keys(cg.childAssets)) {
|
1100
|
const assets = cg.childAssets[name];
|
1101
|
if (assets && assets.length > 0) {
|
1102
|
colors.normal(" ");
|
1103
|
colors.magenta(`(${name}:`);
|
1104
|
for (const asset of assets) {
|
1105
|
colors.normal(" ");
|
1106
|
colors.green(asset);
|
1107
|
}
|
1108
|
colors.magenta(")");
|
1109
|
}
|
1110
|
}
|
1111
|
newline();
|
1112
|
}
|
1113
|
};
|
1114
|
|
1115
|
if (obj.entrypoints) {
|
1116
|
processChunkGroups(obj.entrypoints, "Entrypoint");
|
1117
|
}
|
1118
|
|
1119
|
if (obj.namedChunkGroups) {
|
1120
|
let outputChunkGroups = obj.namedChunkGroups;
|
1121
|
if (obj.entrypoints) {
|
1122
|
outputChunkGroups = Object.keys(outputChunkGroups)
|
1123
|
.filter(name => !obj.entrypoints[name])
|
1124
|
.reduce((result, name) => {
|
1125
|
result[name] = obj.namedChunkGroups[name];
|
1126
|
return result;
|
1127
|
}, {});
|
1128
|
}
|
1129
|
processChunkGroups(outputChunkGroups, "Chunk Group");
|
1130
|
}
|
1131
|
|
1132
|
const modulesByIdentifier = {};
|
1133
|
if (obj.modules) {
|
1134
|
for (const module of obj.modules) {
|
1135
|
modulesByIdentifier[`$${module.identifier}`] = module;
|
1136
|
}
|
1137
|
} else if (obj.chunks) {
|
1138
|
for (const chunk of obj.chunks) {
|
1139
|
if (chunk.modules) {
|
1140
|
for (const module of chunk.modules) {
|
1141
|
modulesByIdentifier[`$${module.identifier}`] = module;
|
1142
|
}
|
1143
|
}
|
1144
|
}
|
1145
|
}
|
1146
|
|
1147
|
const processModuleAttributes = module => {
|
1148
|
colors.normal(" ");
|
1149
|
colors.normal(SizeFormatHelpers.formatSize(module.size));
|
1150
|
if (module.chunks) {
|
1151
|
for (const chunk of module.chunks) {
|
1152
|
colors.normal(" {");
|
1153
|
colors.yellow(chunk);
|
1154
|
colors.normal("}");
|
1155
|
}
|
1156
|
}
|
1157
|
if (typeof module.depth === "number") {
|
1158
|
colors.normal(` [depth ${module.depth}]`);
|
1159
|
}
|
1160
|
if (module.cacheable === false) {
|
1161
|
colors.red(" [not cacheable]");
|
1162
|
}
|
1163
|
if (module.optional) {
|
1164
|
colors.yellow(" [optional]");
|
1165
|
}
|
1166
|
if (module.built) {
|
1167
|
colors.green(" [built]");
|
1168
|
}
|
1169
|
if (module.assets && module.assets.length) {
|
1170
|
colors.magenta(
|
1171
|
` [${module.assets.length} asset${
|
1172
|
module.assets.length === 1 ? "" : "s"
|
1173
|
}]`
|
1174
|
);
|
1175
|
}
|
1176
|
if (module.prefetched) {
|
1177
|
colors.magenta(" [prefetched]");
|
1178
|
}
|
1179
|
if (module.failed) colors.red(" [failed]");
|
1180
|
if (module.warnings) {
|
1181
|
colors.yellow(
|
1182
|
` [${module.warnings} warning${module.warnings === 1 ? "" : "s"}]`
|
1183
|
);
|
1184
|
}
|
1185
|
if (module.errors) {
|
1186
|
colors.red(
|
1187
|
` [${module.errors} error${module.errors === 1 ? "" : "s"}]`
|
1188
|
);
|
1189
|
}
|
1190
|
};
|
1191
|
|
1192
|
const processModuleContent = (module, prefix) => {
|
1193
|
if (Array.isArray(module.providedExports)) {
|
1194
|
colors.normal(prefix);
|
1195
|
if (module.providedExports.length === 0) {
|
1196
|
colors.cyan("[no exports]");
|
1197
|
} else {
|
1198
|
colors.cyan(`[exports: ${module.providedExports.join(", ")}]`);
|
1199
|
}
|
1200
|
newline();
|
1201
|
}
|
1202
|
if (module.usedExports !== undefined) {
|
1203
|
if (module.usedExports !== true) {
|
1204
|
colors.normal(prefix);
|
1205
|
if (module.usedExports === null) {
|
1206
|
colors.cyan("[used exports unknown]");
|
1207
|
} else if (module.usedExports === false) {
|
1208
|
colors.cyan("[no exports used]");
|
1209
|
} else if (
|
1210
|
Array.isArray(module.usedExports) &&
|
1211
|
module.usedExports.length === 0
|
1212
|
) {
|
1213
|
colors.cyan("[no exports used]");
|
1214
|
} else if (Array.isArray(module.usedExports)) {
|
1215
|
const providedExportsCount = Array.isArray(module.providedExports)
|
1216
|
? module.providedExports.length
|
1217
|
: null;
|
1218
|
if (
|
1219
|
providedExportsCount !== null &&
|
1220
|
providedExportsCount === module.usedExports.length
|
1221
|
) {
|
1222
|
colors.cyan("[all exports used]");
|
1223
|
} else {
|
1224
|
colors.cyan(
|
1225
|
`[only some exports used: ${module.usedExports.join(", ")}]`
|
1226
|
);
|
1227
|
}
|
1228
|
}
|
1229
|
newline();
|
1230
|
}
|
1231
|
}
|
1232
|
if (Array.isArray(module.optimizationBailout)) {
|
1233
|
for (const item of module.optimizationBailout) {
|
1234
|
colors.normal(prefix);
|
1235
|
colors.yellow(item);
|
1236
|
newline();
|
1237
|
}
|
1238
|
}
|
1239
|
if (module.reasons) {
|
1240
|
for (const reason of module.reasons) {
|
1241
|
colors.normal(prefix);
|
1242
|
if (reason.type) {
|
1243
|
colors.normal(reason.type);
|
1244
|
colors.normal(" ");
|
1245
|
}
|
1246
|
if (reason.userRequest) {
|
1247
|
colors.cyan(reason.userRequest);
|
1248
|
colors.normal(" ");
|
1249
|
}
|
1250
|
if (reason.moduleId !== null) {
|
1251
|
colors.normal("[");
|
1252
|
colors.normal(reason.moduleId);
|
1253
|
colors.normal("]");
|
1254
|
}
|
1255
|
if (reason.module && reason.module !== reason.moduleId) {
|
1256
|
colors.normal(" ");
|
1257
|
colors.magenta(reason.module);
|
1258
|
}
|
1259
|
if (reason.loc) {
|
1260
|
colors.normal(" ");
|
1261
|
colors.normal(reason.loc);
|
1262
|
}
|
1263
|
if (reason.explanation) {
|
1264
|
colors.normal(" ");
|
1265
|
colors.cyan(reason.explanation);
|
1266
|
}
|
1267
|
newline();
|
1268
|
}
|
1269
|
}
|
1270
|
if (module.profile) {
|
1271
|
colors.normal(prefix);
|
1272
|
let sum = 0;
|
1273
|
if (module.issuerPath) {
|
1274
|
for (const m of module.issuerPath) {
|
1275
|
colors.normal("[");
|
1276
|
colors.normal(m.id);
|
1277
|
colors.normal("] ");
|
1278
|
if (m.profile) {
|
1279
|
const time = (m.profile.factory || 0) + (m.profile.building || 0);
|
1280
|
coloredTime(time);
|
1281
|
sum += time;
|
1282
|
colors.normal(" ");
|
1283
|
}
|
1284
|
colors.normal("-> ");
|
1285
|
}
|
1286
|
}
|
1287
|
for (const key of Object.keys(module.profile)) {
|
1288
|
colors.normal(`${key}:`);
|
1289
|
const time = module.profile[key];
|
1290
|
coloredTime(time);
|
1291
|
colors.normal(" ");
|
1292
|
sum += time;
|
1293
|
}
|
1294
|
colors.normal("= ");
|
1295
|
coloredTime(sum);
|
1296
|
newline();
|
1297
|
}
|
1298
|
if (module.modules) {
|
1299
|
processModulesList(module, prefix + "| ");
|
1300
|
}
|
1301
|
};
|
1302
|
|
1303
|
const processModulesList = (obj, prefix) => {
|
1304
|
if (obj.modules) {
|
1305
|
let maxModuleId = 0;
|
1306
|
for (const module of obj.modules) {
|
1307
|
if (typeof module.id === "number") {
|
1308
|
if (maxModuleId < module.id) maxModuleId = module.id;
|
1309
|
}
|
1310
|
}
|
1311
|
let contentPrefix = prefix + " ";
|
1312
|
if (maxModuleId >= 10) contentPrefix += " ";
|
1313
|
if (maxModuleId >= 100) contentPrefix += " ";
|
1314
|
if (maxModuleId >= 1000) contentPrefix += " ";
|
1315
|
for (const module of obj.modules) {
|
1316
|
colors.normal(prefix);
|
1317
|
const name = module.name || module.identifier;
|
1318
|
if (typeof module.id === "string" || typeof module.id === "number") {
|
1319
|
if (typeof module.id === "number") {
|
1320
|
if (module.id < 1000 && maxModuleId >= 1000) colors.normal(" ");
|
1321
|
if (module.id < 100 && maxModuleId >= 100) colors.normal(" ");
|
1322
|
if (module.id < 10 && maxModuleId >= 10) colors.normal(" ");
|
1323
|
} else {
|
1324
|
if (maxModuleId >= 1000) colors.normal(" ");
|
1325
|
if (maxModuleId >= 100) colors.normal(" ");
|
1326
|
if (maxModuleId >= 10) colors.normal(" ");
|
1327
|
}
|
1328
|
if (name !== module.id) {
|
1329
|
colors.normal("[");
|
1330
|
colors.normal(module.id);
|
1331
|
colors.normal("]");
|
1332
|
colors.normal(" ");
|
1333
|
} else {
|
1334
|
colors.normal("[");
|
1335
|
colors.bold(module.id);
|
1336
|
colors.normal("]");
|
1337
|
}
|
1338
|
}
|
1339
|
if (name !== module.id) {
|
1340
|
colors.bold(name);
|
1341
|
}
|
1342
|
processModuleAttributes(module);
|
1343
|
newline();
|
1344
|
processModuleContent(module, contentPrefix);
|
1345
|
}
|
1346
|
if (obj.filteredModules > 0) {
|
1347
|
colors.normal(prefix);
|
1348
|
colors.normal(" ");
|
1349
|
if (obj.modules.length > 0) colors.normal(" + ");
|
1350
|
colors.normal(obj.filteredModules);
|
1351
|
if (obj.modules.length > 0) colors.normal(" hidden");
|
1352
|
colors.normal(obj.filteredModules !== 1 ? " modules" : " module");
|
1353
|
newline();
|
1354
|
}
|
1355
|
}
|
1356
|
};
|
1357
|
|
1358
|
if (obj.chunks) {
|
1359
|
for (const chunk of obj.chunks) {
|
1360
|
colors.normal("chunk ");
|
1361
|
if (chunk.id < 1000) colors.normal(" ");
|
1362
|
if (chunk.id < 100) colors.normal(" ");
|
1363
|
if (chunk.id < 10) colors.normal(" ");
|
1364
|
colors.normal("{");
|
1365
|
colors.yellow(chunk.id);
|
1366
|
colors.normal("} ");
|
1367
|
colors.green(chunk.files.join(", "));
|
1368
|
if (chunk.names && chunk.names.length > 0) {
|
1369
|
colors.normal(" (");
|
1370
|
colors.normal(chunk.names.join(", "));
|
1371
|
colors.normal(")");
|
1372
|
}
|
1373
|
colors.normal(" ");
|
1374
|
colors.normal(SizeFormatHelpers.formatSize(chunk.size));
|
1375
|
for (const id of chunk.parents) {
|
1376
|
colors.normal(" <{");
|
1377
|
colors.yellow(id);
|
1378
|
colors.normal("}>");
|
1379
|
}
|
1380
|
for (const id of chunk.siblings) {
|
1381
|
colors.normal(" ={");
|
1382
|
colors.yellow(id);
|
1383
|
colors.normal("}=");
|
1384
|
}
|
1385
|
for (const id of chunk.children) {
|
1386
|
colors.normal(" >{");
|
1387
|
colors.yellow(id);
|
1388
|
colors.normal("}<");
|
1389
|
}
|
1390
|
if (chunk.childrenByOrder) {
|
1391
|
for (const name of Object.keys(chunk.childrenByOrder)) {
|
1392
|
const children = chunk.childrenByOrder[name];
|
1393
|
colors.normal(" ");
|
1394
|
colors.magenta(`(${name}:`);
|
1395
|
for (const id of children) {
|
1396
|
colors.normal(" {");
|
1397
|
colors.yellow(id);
|
1398
|
colors.normal("}");
|
1399
|
}
|
1400
|
colors.magenta(")");
|
1401
|
}
|
1402
|
}
|
1403
|
if (chunk.entry) {
|
1404
|
colors.yellow(" [entry]");
|
1405
|
} else if (chunk.initial) {
|
1406
|
colors.yellow(" [initial]");
|
1407
|
}
|
1408
|
if (chunk.rendered) {
|
1409
|
colors.green(" [rendered]");
|
1410
|
}
|
1411
|
if (chunk.recorded) {
|
1412
|
colors.green(" [recorded]");
|
1413
|
}
|
1414
|
if (chunk.reason) {
|
1415
|
colors.yellow(` ${chunk.reason}`);
|
1416
|
}
|
1417
|
newline();
|
1418
|
if (chunk.origins) {
|
1419
|
for (const origin of chunk.origins) {
|
1420
|
colors.normal(" > ");
|
1421
|
if (origin.reasons && origin.reasons.length) {
|
1422
|
colors.yellow(origin.reasons.join(" "));
|
1423
|
colors.normal(" ");
|
1424
|
}
|
1425
|
if (origin.request) {
|
1426
|
colors.normal(origin.request);
|
1427
|
colors.normal(" ");
|
1428
|
}
|
1429
|
if (origin.module) {
|
1430
|
colors.normal("[");
|
1431
|
colors.normal(origin.moduleId);
|
1432
|
colors.normal("] ");
|
1433
|
const module = modulesByIdentifier[`$${origin.module}`];
|
1434
|
if (module) {
|
1435
|
colors.bold(module.name);
|
1436
|
colors.normal(" ");
|
1437
|
}
|
1438
|
}
|
1439
|
if (origin.loc) {
|
1440
|
colors.normal(origin.loc);
|
1441
|
}
|
1442
|
newline();
|
1443
|
}
|
1444
|
}
|
1445
|
processModulesList(chunk, " ");
|
1446
|
}
|
1447
|
}
|
1448
|
|
1449
|
processModulesList(obj, "");
|
1450
|
|
1451
|
if (obj.logging) {
|
1452
|
for (const origin of Object.keys(obj.logging)) {
|
1453
|
const logData = obj.logging[origin];
|
1454
|
if (logData.entries.length > 0) {
|
1455
|
newline();
|
1456
|
if (logData.debug) {
|
1457
|
colors.red("DEBUG ");
|
1458
|
}
|
1459
|
colors.bold("LOG from " + origin);
|
1460
|
newline();
|
1461
|
let indent = "";
|
1462
|
for (const entry of logData.entries) {
|
1463
|
let color = colors.normal;
|
1464
|
let prefix = " ";
|
1465
|
switch (entry.type) {
|
1466
|
case LogType.clear:
|
1467
|
colors.normal(`${indent}-------`);
|
1468
|
newline();
|
1469
|
continue;
|
1470
|
case LogType.error:
|
1471
|
color = colors.red;
|
1472
|
prefix = "<e> ";
|
1473
|
break;
|
1474
|
case LogType.warn:
|
1475
|
color = colors.yellow;
|
1476
|
prefix = "<w> ";
|
1477
|
break;
|
1478
|
case LogType.info:
|
1479
|
color = colors.green;
|
1480
|
prefix = "<i> ";
|
1481
|
break;
|
1482
|
case LogType.log:
|
1483
|
color = colors.bold;
|
1484
|
break;
|
1485
|
case LogType.trace:
|
1486
|
case LogType.debug:
|
1487
|
color = colors.normal;
|
1488
|
break;
|
1489
|
case LogType.status:
|
1490
|
color = colors.magenta;
|
1491
|
prefix = "<s> ";
|
1492
|
break;
|
1493
|
case LogType.profile:
|
1494
|
color = colors.magenta;
|
1495
|
prefix = "<p> ";
|
1496
|
break;
|
1497
|
case LogType.profileEnd:
|
1498
|
color = colors.magenta;
|
1499
|
prefix = "</p> ";
|
1500
|
break;
|
1501
|
case LogType.time:
|
1502
|
color = colors.magenta;
|
1503
|
prefix = "<t> ";
|
1504
|
break;
|
1505
|
case LogType.group:
|
1506
|
color = colors.cyan;
|
1507
|
prefix = "<-> ";
|
1508
|
break;
|
1509
|
case LogType.groupCollapsed:
|
1510
|
color = colors.cyan;
|
1511
|
prefix = "<+> ";
|
1512
|
break;
|
1513
|
case LogType.groupEnd:
|
1514
|
if (indent.length >= 2)
|
1515
|
indent = indent.slice(0, indent.length - 2);
|
1516
|
continue;
|
1517
|
}
|
1518
|
if (entry.message) {
|
1519
|
for (const line of entry.message.split("\n")) {
|
1520
|
colors.normal(`${indent}${prefix}`);
|
1521
|
color(line);
|
1522
|
newline();
|
1523
|
}
|
1524
|
}
|
1525
|
if (entry.trace) {
|
1526
|
for (const line of entry.trace) {
|
1527
|
colors.normal(`${indent}| ${line}`);
|
1528
|
newline();
|
1529
|
}
|
1530
|
}
|
1531
|
switch (entry.type) {
|
1532
|
case LogType.group:
|
1533
|
indent += " ";
|
1534
|
break;
|
1535
|
}
|
1536
|
}
|
1537
|
if (logData.filteredEntries) {
|
1538
|
colors.normal(`+ ${logData.filteredEntries} hidden lines`);
|
1539
|
newline();
|
1540
|
}
|
1541
|
}
|
1542
|
}
|
1543
|
}
|
1544
|
|
1545
|
if (obj._showWarnings && obj.warnings) {
|
1546
|
for (const warning of obj.warnings) {
|
1547
|
newline();
|
1548
|
colors.yellow(`WARNING in ${warning}`);
|
1549
|
newline();
|
1550
|
}
|
1551
|
}
|
1552
|
if (obj._showErrors && obj.errors) {
|
1553
|
for (const error of obj.errors) {
|
1554
|
newline();
|
1555
|
colors.red(`ERROR in ${error}`);
|
1556
|
newline();
|
1557
|
}
|
1558
|
}
|
1559
|
if (obj.children) {
|
1560
|
for (const child of obj.children) {
|
1561
|
const childString = Stats.jsonToString(child, useColors);
|
1562
|
if (childString) {
|
1563
|
if (child.name) {
|
1564
|
colors.normal("Child ");
|
1565
|
colors.bold(child.name);
|
1566
|
colors.normal(":");
|
1567
|
} else {
|
1568
|
colors.normal("Child");
|
1569
|
}
|
1570
|
newline();
|
1571
|
buf.push(" ");
|
1572
|
buf.push(childString.replace(/\n/g, "\n "));
|
1573
|
newline();
|
1574
|
}
|
1575
|
}
|
1576
|
}
|
1577
|
if (obj.needAdditionalPass) {
|
1578
|
colors.yellow(
|
1579
|
"Compilation needs an additional pass and will compile again."
|
1580
|
);
|
1581
|
}
|
1582
|
|
1583
|
while (buf[buf.length - 1] === "\n") {
|
1584
|
buf.pop();
|
1585
|
}
|
1586
|
return buf.join("");
|
1587
|
}
|
1588
|
|
1589
|
static presetToOptions(name) {
|
1590
|
// Accepted values: none, errors-only, minimal, normal, detailed, verbose
|
1591
|
// Any other falsy value will behave as 'none', truthy values as 'normal'
|
1592
|
const pn =
|
1593
|
(typeof name === "string" && name.toLowerCase()) || name || "none";
|
1594
|
switch (pn) {
|
1595
|
case "none":
|
1596
|
return {
|
1597
|
all: false
|
1598
|
};
|
1599
|
case "verbose":
|
1600
|
return {
|
1601
|
entrypoints: true,
|
1602
|
chunkGroups: true,
|
1603
|
modules: false,
|
1604
|
chunks: true,
|
1605
|
chunkModules: true,
|
1606
|
chunkOrigins: true,
|
1607
|
depth: true,
|
1608
|
env: true,
|
1609
|
reasons: true,
|
1610
|
usedExports: true,
|
1611
|
providedExports: true,
|
1612
|
optimizationBailout: true,
|
1613
|
errorDetails: true,
|
1614
|
publicPath: true,
|
1615
|
logging: "verbose",
|
1616
|
exclude: false,
|
1617
|
maxModules: Infinity
|
1618
|
};
|
1619
|
case "detailed":
|
1620
|
return {
|
1621
|
entrypoints: true,
|
1622
|
chunkGroups: true,
|
1623
|
chunks: true,
|
1624
|
chunkModules: false,
|
1625
|
chunkOrigins: true,
|
1626
|
depth: true,
|
1627
|
usedExports: true,
|
1628
|
providedExports: true,
|
1629
|
optimizationBailout: true,
|
1630
|
errorDetails: true,
|
1631
|
publicPath: true,
|
1632
|
logging: true,
|
1633
|
exclude: false,
|
1634
|
maxModules: Infinity
|
1635
|
};
|
1636
|
case "minimal":
|
1637
|
return {
|
1638
|
all: false,
|
1639
|
modules: true,
|
1640
|
maxModules: 0,
|
1641
|
errors: true,
|
1642
|
warnings: true,
|
1643
|
logging: "warn"
|
1644
|
};
|
1645
|
case "errors-only":
|
1646
|
return {
|
1647
|
all: false,
|
1648
|
errors: true,
|
1649
|
moduleTrace: true,
|
1650
|
logging: "error"
|
1651
|
};
|
1652
|
case "errors-warnings":
|
1653
|
return {
|
1654
|
all: false,
|
1655
|
errors: true,
|
1656
|
warnings: true,
|
1657
|
logging: "warn"
|
1658
|
};
|
1659
|
default:
|
1660
|
return {};
|
1661
|
}
|
1662
|
}
|
1663
|
|
1664
|
static getChildOptions(options, idx) {
|
1665
|
let innerOptions;
|
1666
|
if (Array.isArray(options.children)) {
|
1667
|
if (idx < options.children.length) {
|
1668
|
innerOptions = options.children[idx];
|
1669
|
}
|
1670
|
} else if (typeof options.children === "object" && options.children) {
|
1671
|
innerOptions = options.children;
|
1672
|
}
|
1673
|
if (typeof innerOptions === "boolean" || typeof innerOptions === "string") {
|
1674
|
innerOptions = Stats.presetToOptions(innerOptions);
|
1675
|
}
|
1676
|
if (!innerOptions) {
|
1677
|
return options;
|
1678
|
}
|
1679
|
const childOptions = Object.assign({}, options);
|
1680
|
delete childOptions.children; // do not inherit children
|
1681
|
return Object.assign(childOptions, innerOptions);
|
1682
|
}
|
1683
|
}
|
1684
|
|
1685
|
module.exports = Stats;
|