webpack 4.36.0 → 4.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/Compiler.js CHANGED
@@ -27,6 +27,7 @@ const ResolverFactory = require("./ResolverFactory");
27
27
  const RequestShortener = require("./RequestShortener");
28
28
  const { makePathsRelative } = require("./util/identifier");
29
29
  const ConcurrentCompilationError = require("./ConcurrentCompilationError");
30
+ const { Logger } = require("./logging/Logger");
30
31
 
31
32
  /** @typedef {import("../declarations/WebpackOptions").Entry} Entry */
32
33
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
@@ -54,6 +55,8 @@ class Compiler extends Tapable {
54
55
  run: new AsyncSeriesHook(["compiler"]),
55
56
  /** @type {AsyncSeriesHook<Compilation>} */
56
57
  emit: new AsyncSeriesHook(["compilation"]),
58
+ /** @type {AsyncSeriesHook<string, Buffer>} */
59
+ assetEmitted: new AsyncSeriesHook(["file", "content"]),
57
60
  /** @type {AsyncSeriesHook<Compilation>} */
58
61
  afterEmit: new AsyncSeriesHook(["compilation"]),
59
62
 
@@ -84,6 +87,9 @@ class Compiler extends Tapable {
84
87
  /** @type {SyncHook} */
85
88
  watchClose: new SyncHook([]),
86
89
 
90
+ /** @type {SyncBailHook<string, string, any[]>} */
91
+ infrastructureLog: new SyncBailHook(["origin", "type", "args"]),
92
+
87
93
  // TODO the following hooks are weirdly located here
88
94
  // TODO move them for webpack 5
89
95
  /** @type {SyncHook} */
@@ -97,6 +103,8 @@ class Compiler extends Tapable {
97
103
  /** @type {SyncBailHook<string, Entry>} */
98
104
  entryOption: new SyncBailHook(["context", "entry"])
99
105
  };
106
+ // TODO webpack 5 remove this
107
+ this.hooks.infrastructurelog = this.hooks.infrastructureLog;
100
108
 
101
109
  this._pluginCompat.tap("Compiler", options => {
102
110
  switch (options.name) {
@@ -137,6 +145,8 @@ class Compiler extends Tapable {
137
145
  /** @type {ResolverFactory} */
138
146
  this.resolverFactory = new ResolverFactory();
139
147
 
148
+ this.infrastructureLogger = undefined;
149
+
140
150
  // TODO remove in webpack 5
141
151
  this.resolvers = {
142
152
  normal: {
@@ -196,6 +206,33 @@ class Compiler extends Tapable {
196
206
  this._assetEmittingWrittenFiles = new Map();
197
207
  }
198
208
 
209
+ /**
210
+ * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name
211
+ * @returns {Logger} a logger with that name
212
+ */
213
+ getInfrastructureLogger(name) {
214
+ if (!name) {
215
+ throw new TypeError(
216
+ "Compiler.getInfrastructureLogger(name) called without a name"
217
+ );
218
+ }
219
+ return new Logger((type, args) => {
220
+ if (typeof name === "function") {
221
+ name = name();
222
+ if (!name) {
223
+ throw new TypeError(
224
+ "Compiler.getInfrastructureLogger(name) called with a function not returning a name"
225
+ );
226
+ }
227
+ }
228
+ if (this.hooks.infrastructureLog.call(name, type, args) === undefined) {
229
+ if (this.infrastructureLogger !== undefined) {
230
+ this.infrastructureLogger(name, type, args);
231
+ }
232
+ }
233
+ });
234
+ }
235
+
199
236
  watch(watchOptions, handler) {
200
237
  if (this.running) return handler(new ConcurrentCompilationError());
201
238
 
@@ -397,7 +434,7 @@ class Compiler extends Tapable {
397
434
  : targetFileGeneration + 1;
398
435
  cacheEntry.writtenTo.set(targetPath, newGeneration);
399
436
  this._assetEmittingWrittenFiles.set(targetPath, newGeneration);
400
- callback();
437
+ this.hooks.assetEmitted.callAsync(file, content, callback);
401
438
  });
402
439
  } else {
403
440
  if (source.existsAt === targetPath) {
@@ -412,7 +449,10 @@ class Compiler extends Tapable {
412
449
 
413
450
  source.existsAt = targetPath;
414
451
  source.emitted = true;
415
- this.outputFileSystem.writeFile(targetPath, content, callback);
452
+ this.outputFileSystem.writeFile(targetPath, content, err => {
453
+ if (err) return callback(err);
454
+ this.hooks.assetEmitted.callAsync(file, content, callback);
455
+ });
416
456
  }
417
457
  };
418
458
 
@@ -18,7 +18,10 @@ module.exports = class MultiCompiler extends Tapable {
18
18
  invalid: new MultiHook(compilers.map(c => c.hooks.invalid)),
19
19
  run: new MultiHook(compilers.map(c => c.hooks.run)),
20
20
  watchClose: new SyncHook([]),
21
- watchRun: new MultiHook(compilers.map(c => c.hooks.watchRun))
21
+ watchRun: new MultiHook(compilers.map(c => c.hooks.watchRun)),
22
+ infrastructureLog: new MultiHook(
23
+ compilers.map(c => c.hooks.infrastructureLog)
24
+ )
22
25
  };
23
26
  if (!Array.isArray(compilers)) {
24
27
  compilers = Object.keys(compilers).map(name => {
@@ -90,6 +93,10 @@ module.exports = class MultiCompiler extends Tapable {
90
93
  }
91
94
  }
92
95
 
96
+ getInfrastructureLogger(name) {
97
+ return this.compilers[0].getInfrastructureLogger(name);
98
+ }
99
+
93
100
  validateDependencies(callback) {
94
101
  const edges = new Set();
95
102
  const missing = [];
@@ -147,16 +147,20 @@ class NormalModule extends Module {
147
147
 
148
148
  createLoaderContext(resolver, options, compilation, fs) {
149
149
  const requestShortener = compilation.runtimeTemplate.requestShortener;
150
+ const getCurrentLoaderName = () => {
151
+ const currentLoader = this.getCurrentLoader(loaderContext);
152
+ if (!currentLoader) return "(not in loader scope)";
153
+ return requestShortener.shorten(currentLoader.loader);
154
+ };
150
155
  const loaderContext = {
151
156
  version: 2,
152
157
  emitWarning: warning => {
153
158
  if (!(warning instanceof Error)) {
154
159
  warning = new NonErrorEmittedError(warning);
155
160
  }
156
- const currentLoader = this.getCurrentLoader(loaderContext);
157
161
  this.warnings.push(
158
162
  new ModuleWarning(this, warning, {
159
- from: requestShortener.shorten(currentLoader.loader)
163
+ from: getCurrentLoaderName()
160
164
  })
161
165
  );
162
166
  },
@@ -164,13 +168,20 @@ class NormalModule extends Module {
164
168
  if (!(error instanceof Error)) {
165
169
  error = new NonErrorEmittedError(error);
166
170
  }
167
- const currentLoader = this.getCurrentLoader(loaderContext);
168
171
  this.errors.push(
169
172
  new ModuleError(this, error, {
170
- from: requestShortener.shorten(currentLoader.loader)
173
+ from: getCurrentLoaderName()
171
174
  })
172
175
  );
173
176
  },
177
+ getLogger: name => {
178
+ const currentLoader = this.getCurrentLoader(loaderContext);
179
+ return compilation.getLogger(() =>
180
+ [currentLoader && currentLoader.loader, name, this.identifier()]
181
+ .filter(Boolean)
182
+ .join("|")
183
+ );
184
+ },
174
185
  // TODO remove in webpack 5
175
186
  exec: (code, filename) => {
176
187
  // @ts-ignore Argument of type 'this' is not assignable to parameter of type 'Module'.
@@ -10,50 +10,14 @@ const schema = require("../schemas/plugins/ProgressPlugin.json");
10
10
  /** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginArgument} ProgressPluginArgument */
11
11
  /** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginOptions} ProgressPluginOptions */
12
12
 
13
- const createDefaultHandler = profile => {
14
- let lineCaretPosition = 0;
15
- let lastMessage = "";
13
+ const createDefaultHandler = (profile, logger) => {
16
14
  let lastState;
17
15
  let lastStateTime;
18
16
 
19
17
  const defaultHandler = (percentage, msg, ...args) => {
20
- let state = msg;
21
- const details = args.filter(v => v.length);
22
- const maxLineLength = process.stderr.columns || Infinity;
23
- if (percentage < 1) {
24
- percentage = Math.floor(percentage * 100);
25
- msg = `${percentage}% ${msg}`;
26
- if (percentage < 100) {
27
- msg = ` ${msg}`;
28
- }
29
- if (percentage < 10) {
30
- msg = ` ${msg}`;
31
- }
32
-
33
- if (details.length) {
34
- const maxTotalDetailsLength = maxLineLength - msg.length;
35
- const totalDetailsLength = details.reduce(
36
- (a, b) => a + b.length,
37
- details.length // account for added space before each detail text
38
- );
39
- const maxDetailLength =
40
- totalDetailsLength < maxTotalDetailsLength
41
- ? Infinity
42
- : Math.floor(maxTotalDetailsLength / details.length);
43
-
44
- for (let detail of details) {
45
- if (!detail) continue;
46
- if (detail.length + 1 > maxDetailLength) {
47
- const truncatePrefix = "...";
48
- detail = `${truncatePrefix}${detail.substr(
49
- -(maxDetailLength - truncatePrefix.length - 1)
50
- )}`;
51
- }
52
- msg += ` ${detail}`;
53
- }
54
- }
55
- }
18
+ logger.status(`${Math.floor(percentage * 100)}%`, msg, ...args);
56
19
  if (profile) {
20
+ let state = msg;
57
21
  state = state.replace(/^\d+\/\d+\s+/, "");
58
22
  if (percentage === 0) {
59
23
  lastState = null;
@@ -61,33 +25,23 @@ const createDefaultHandler = profile => {
61
25
  } else if (state !== lastState || percentage === 1) {
62
26
  const now = Date.now();
63
27
  if (lastState) {
64
- const stateMsg = `${now - lastStateTime}ms ${lastState}`;
65
- goToLineStart(stateMsg);
66
- process.stderr.write(stateMsg + "\n");
67
- lineCaretPosition = 0;
28
+ const diff = now - lastStateTime;
29
+ const stateMsg = `${diff}ms ${lastState}`;
30
+ if (diff > 1000) {
31
+ logger.warn(stateMsg);
32
+ } else if (diff > 10) {
33
+ logger.info(stateMsg);
34
+ } else if (diff > 0) {
35
+ logger.log(stateMsg);
36
+ } else {
37
+ logger.debug(stateMsg);
38
+ }
68
39
  }
69
40
  lastState = state;
70
41
  lastStateTime = now;
71
42
  }
72
43
  }
73
- if (lastMessage !== msg) {
74
- goToLineStart(msg);
75
- msg = msg.substring(0, maxLineLength);
76
- process.stderr.write(msg);
77
- lastMessage = msg;
78
- }
79
- };
80
-
81
- const goToLineStart = nextMessage => {
82
- let str = "";
83
- for (; lineCaretPosition > nextMessage.length; lineCaretPosition--) {
84
- str += "\b \b";
85
- }
86
- for (var i = 0; i < lineCaretPosition; i++) {
87
- str += "\b";
88
- }
89
- lineCaretPosition = nextMessage.length;
90
- if (str) process.stderr.write(str);
44
+ if (percentage === 1) logger.status();
91
45
  };
92
46
 
93
47
  return defaultHandler;
@@ -118,7 +72,12 @@ class ProgressPlugin {
118
72
 
119
73
  apply(compiler) {
120
74
  const { modulesCount } = this;
121
- const handler = this.handler || createDefaultHandler(this.profile);
75
+ const handler =
76
+ this.handler ||
77
+ createDefaultHandler(
78
+ this.profile,
79
+ compiler.getInfrastructureLogger("webpack.Progress")
80
+ );
122
81
  const showEntries = this.showEntries;
123
82
  const showModules = this.showModules;
124
83
  const showActiveModules = this.showActiveModules;
@@ -263,7 +222,6 @@ class ProgressPlugin {
263
222
  recordModules: "record modules",
264
223
  recordChunks: "record chunks",
265
224
  beforeHash: "hashing",
266
- contentHash: "content hashing",
267
225
  afterHash: "after hashing",
268
226
  recordHash: "record hash",
269
227
  beforeModuleAssets: "module assets processing",
@@ -10,6 +10,8 @@ const { cachedCleverMerge } = require("./util/cleverMerge");
10
10
 
11
11
  /** @typedef {import("enhanced-resolve").Resolver} Resolver */
12
12
 
13
+ const EMTPY_RESOLVE_OPTIONS = {};
14
+
13
15
  module.exports = class ResolverFactory extends Tapable {
14
16
  constructor() {
15
17
  super();
@@ -23,30 +25,24 @@ module.exports = class ResolverFactory extends Tapable {
23
25
  let match;
24
26
  match = /^resolve-options (.+)$/.exec(options.name);
25
27
  if (match) {
26
- this.hooks.resolveOptions.tap(
27
- match[1],
28
- options.fn.name || "unnamed compat plugin",
29
- options.fn
30
- );
28
+ this.hooks.resolveOptions
29
+ .for(match[1])
30
+ .tap(options.fn.name || "unnamed compat plugin", options.fn);
31
31
  return true;
32
32
  }
33
33
  match = /^resolver (.+)$/.exec(options.name);
34
34
  if (match) {
35
- this.hooks.resolver.tap(
36
- match[1],
37
- options.fn.name || "unnamed compat plugin",
38
- options.fn
39
- );
35
+ this.hooks.resolver
36
+ .for(match[1])
37
+ .tap(options.fn.name || "unnamed compat plugin", options.fn);
40
38
  return true;
41
39
  }
42
40
  });
43
- this.cache1 = new WeakMap();
44
41
  this.cache2 = new Map();
45
42
  }
46
43
 
47
44
  get(type, resolveOptions) {
48
- const cachedResolver = this.cache1.get(resolveOptions);
49
- if (cachedResolver) return cachedResolver();
45
+ resolveOptions = resolveOptions || EMTPY_RESOLVE_OPTIONS;
50
46
  const ident = `${type}|${JSON.stringify(resolveOptions)}`;
51
47
  const resolver = this.cache2.get(ident);
52
48
  if (resolver) return resolver;
@@ -49,27 +49,13 @@ const assetsCache = new WeakMap();
49
49
  /**
50
50
  * Creating {@link SourceMapTask} for given file
51
51
  * @param {string} file current compiled file
52
+ * @param {Source} asset the asset
52
53
  * @param {Chunk} chunk related chunk
53
54
  * @param {SourceMapDevToolPluginOptions} options source map options
54
55
  * @param {Compilation} compilation compilation instance
55
56
  * @returns {SourceMapTask | undefined} created task instance or `undefined`
56
57
  */
57
- const getTaskForFile = (file, chunk, options, compilation) => {
58
- const asset = compilation.assets[file];
59
- const cache = assetsCache.get(asset);
60
- /**
61
- * If presented in cache, reassigns assets. Cache assets already have source maps.
62
- */
63
- if (cache && cache.file === file) {
64
- for (const cachedFile in cache.assets) {
65
- compilation.assets[cachedFile] = cache.assets[cachedFile];
66
- /**
67
- * Add file to chunk, if not presented there
68
- */
69
- if (cachedFile !== file) chunk.files.push(cachedFile);
70
- }
71
- return;
72
- }
58
+ const getTaskForFile = (file, asset, chunk, options, compilation) => {
73
59
  let source, sourceMap;
74
60
  /**
75
61
  * Check if asset can build source map
@@ -189,13 +175,35 @@ class SourceMapDevToolPlugin {
189
175
  reportProgress(0.0);
190
176
  const tasks = [];
191
177
  files.forEach(({ file, chunk }, idx) => {
178
+ const asset = compilation.assets[file];
179
+ const cache = assetsCache.get(asset);
180
+ /**
181
+ * If presented in cache, reassigns assets. Cache assets already have source maps.
182
+ */
183
+ if (cache && cache.file === file) {
184
+ for (const cachedFile in cache.assets) {
185
+ compilation.assets[cachedFile] = cache.assets[cachedFile];
186
+ /**
187
+ * Add file to chunk, if not presented there
188
+ */
189
+ if (cachedFile !== file) chunk.files.push(cachedFile);
190
+ }
191
+ return;
192
+ }
193
+
192
194
  reportProgress(
193
195
  (0.5 * idx) / files.length,
194
196
  file,
195
197
  "generate SourceMap"
196
198
  );
197
199
  /** @type {SourceMapTask | undefined} */
198
- const task = getTaskForFile(file, chunk, options, compilation);
200
+ const task = getTaskForFile(
201
+ file,
202
+ asset,
203
+ chunk,
204
+ options,
205
+ compilation
206
+ );
199
207
 
200
208
  if (task) {
201
209
  const modules = task.sourceMap.sources.map(source => {
package/lib/Stats.js CHANGED
@@ -9,6 +9,7 @@ const SizeFormatHelpers = require("./SizeFormatHelpers");
9
9
  const formatLocation = require("./formatLocation");
10
10
  const identifierUtils = require("./util/identifier");
11
11
  const compareLocations = require("./compareLocations");
12
+ const { LogType } = require("./logging/Logger");
12
13
 
13
14
  const optionsOrFallback = (...args) => {
14
15
  let optionValues = [];
@@ -198,6 +199,18 @@ class Stats {
198
199
  options.publicPath,
199
200
  !forToString
200
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
+
201
214
  const excludeModules = []
202
215
  .concat(optionsOrFallback(options.excludeModules, options.exclude, []))
203
216
  .map(testAgainstGivenOption);
@@ -699,6 +712,118 @@ class Stats {
699
712
  obj.filteredModules = compilation.modules.length - obj.modules.length;
700
713
  obj.modules.sort(sortByField(sortModules, obj.modules));
701
714
  }
715
+ if (showLogging) {
716
+ const util = require("util");
717
+ obj.logging = {};
718
+ let acceptedTypes;
719
+ let collapsedGroups = false;
720
+ switch (showLogging) {
721
+ case "none":
722
+ acceptedTypes = new Set([]);
723
+ break;
724
+ case "error":
725
+ acceptedTypes = new Set([LogType.error]);
726
+ break;
727
+ case "warn":
728
+ acceptedTypes = new Set([LogType.error, LogType.warn]);
729
+ break;
730
+ case "info":
731
+ acceptedTypes = new Set([LogType.error, LogType.warn, LogType.info]);
732
+ break;
733
+ case true:
734
+ case "log":
735
+ acceptedTypes = new Set([
736
+ LogType.error,
737
+ LogType.warn,
738
+ LogType.info,
739
+ LogType.log,
740
+ LogType.group,
741
+ LogType.groupEnd,
742
+ LogType.groupCollapsed,
743
+ LogType.clear
744
+ ]);
745
+ break;
746
+ case "verbose":
747
+ acceptedTypes = new Set([
748
+ LogType.error,
749
+ LogType.warn,
750
+ LogType.info,
751
+ LogType.log,
752
+ LogType.group,
753
+ LogType.groupEnd,
754
+ LogType.groupCollapsed,
755
+ LogType.profile,
756
+ LogType.profileEnd,
757
+ LogType.time,
758
+ LogType.status,
759
+ LogType.clear
760
+ ]);
761
+ collapsedGroups = true;
762
+ break;
763
+ }
764
+ for (const [origin, logEntries] of compilation.logging) {
765
+ const debugMode = loggingDebug.some(fn => fn(origin));
766
+ let collapseCounter = 0;
767
+ let processedLogEntries = logEntries;
768
+ if (!debugMode) {
769
+ processedLogEntries = processedLogEntries.filter(entry => {
770
+ if (!acceptedTypes.has(entry.type)) return false;
771
+ if (!collapsedGroups) {
772
+ switch (entry.type) {
773
+ case LogType.groupCollapsed:
774
+ collapseCounter++;
775
+ return collapseCounter === 1;
776
+ case LogType.group:
777
+ if (collapseCounter > 0) collapseCounter++;
778
+ return collapseCounter === 0;
779
+ case LogType.groupEnd:
780
+ if (collapseCounter > 0) {
781
+ collapseCounter--;
782
+ return false;
783
+ }
784
+ return true;
785
+ default:
786
+ return collapseCounter === 0;
787
+ }
788
+ }
789
+ return true;
790
+ });
791
+ }
792
+ processedLogEntries = processedLogEntries.map(entry => {
793
+ let message = undefined;
794
+ if (entry.type === LogType.time) {
795
+ message = `${entry.args[0]}: ${entry.args[1] * 1000 +
796
+ entry.args[2] / 1000000}ms`;
797
+ } else if (entry.args && entry.args.length > 0) {
798
+ message = util.format(entry.args[0], ...entry.args.slice(1));
799
+ }
800
+ return {
801
+ type:
802
+ (debugMode || collapsedGroups) &&
803
+ entry.type === LogType.groupCollapsed
804
+ ? LogType.group
805
+ : entry.type,
806
+ message,
807
+ trace: showLoggingTrace && entry.trace ? entry.trace : undefined
808
+ };
809
+ });
810
+ let name = identifierUtils
811
+ .makePathsRelative(context, origin, compilation.cache)
812
+ .replace(/\|/g, " ");
813
+ if (name in obj.logging) {
814
+ let i = 1;
815
+ while (`${name}#${i}` in obj.logging) {
816
+ i++;
817
+ }
818
+ name = `${name}#${i}`;
819
+ }
820
+ obj.logging[name] = {
821
+ entries: processedLogEntries,
822
+ filteredEntries: logEntries.length - processedLogEntries.length,
823
+ debug: debugMode
824
+ };
825
+ }
826
+ }
702
827
  if (showChildren) {
703
828
  obj.children = compilation.children.map((child, idx) => {
704
829
  const childOptions = Stats.getChildOptions(options, idx);
@@ -1305,6 +1430,100 @@ class Stats {
1305
1430
 
1306
1431
  processModulesList(obj, "");
1307
1432
 
1433
+ if (obj.logging) {
1434
+ for (const origin of Object.keys(obj.logging)) {
1435
+ const logData = obj.logging[origin];
1436
+ if (logData.entries.length > 0) {
1437
+ newline();
1438
+ if (logData.debug) {
1439
+ colors.red("DEBUG ");
1440
+ }
1441
+ colors.bold("LOG from " + origin);
1442
+ newline();
1443
+ let indent = "";
1444
+ for (const entry of logData.entries) {
1445
+ let color = colors.normal;
1446
+ let prefix = " ";
1447
+ switch (entry.type) {
1448
+ case LogType.clear:
1449
+ colors.normal(`${indent}-------`);
1450
+ newline();
1451
+ continue;
1452
+ case LogType.error:
1453
+ color = colors.red;
1454
+ prefix = "<e> ";
1455
+ break;
1456
+ case LogType.warn:
1457
+ color = colors.yellow;
1458
+ prefix = "<w> ";
1459
+ break;
1460
+ case LogType.info:
1461
+ color = colors.green;
1462
+ prefix = "<i> ";
1463
+ break;
1464
+ case LogType.log:
1465
+ color = colors.bold;
1466
+ break;
1467
+ case LogType.trace:
1468
+ case LogType.debug:
1469
+ color = colors.normal;
1470
+ break;
1471
+ case LogType.status:
1472
+ color = colors.magenta;
1473
+ prefix = "<s> ";
1474
+ break;
1475
+ case LogType.profile:
1476
+ color = colors.magenta;
1477
+ prefix = "<p> ";
1478
+ break;
1479
+ case LogType.profileEnd:
1480
+ color = colors.magenta;
1481
+ prefix = "</p> ";
1482
+ break;
1483
+ case LogType.time:
1484
+ color = colors.magenta;
1485
+ prefix = "<t> ";
1486
+ break;
1487
+ case LogType.group:
1488
+ color = colors.cyan;
1489
+ prefix = "<-> ";
1490
+ break;
1491
+ case LogType.groupCollapsed:
1492
+ color = colors.cyan;
1493
+ prefix = "<+> ";
1494
+ break;
1495
+ case LogType.groupEnd:
1496
+ if (indent.length >= 2)
1497
+ indent = indent.slice(0, indent.length - 2);
1498
+ continue;
1499
+ }
1500
+ if (entry.message) {
1501
+ for (const line of entry.message.split("\n")) {
1502
+ colors.normal(`${indent}${prefix}`);
1503
+ color(line);
1504
+ newline();
1505
+ }
1506
+ }
1507
+ if (entry.trace) {
1508
+ for (const line of entry.trace) {
1509
+ colors.normal(`${indent}| ${line}`);
1510
+ newline();
1511
+ }
1512
+ }
1513
+ switch (entry.type) {
1514
+ case LogType.group:
1515
+ indent += " ";
1516
+ break;
1517
+ }
1518
+ }
1519
+ if (logData.filteredEntries) {
1520
+ colors.normal(`+ ${logData.filteredEntries} hidden lines`);
1521
+ newline();
1522
+ }
1523
+ }
1524
+ }
1525
+ }
1526
+
1308
1527
  if (obj._showWarnings && obj.warnings) {
1309
1528
  for (const warning of obj.warnings) {
1310
1529
  newline();
@@ -1375,6 +1594,7 @@ class Stats {
1375
1594
  optimizationBailout: true,
1376
1595
  errorDetails: true,
1377
1596
  publicPath: true,
1597
+ logging: "verbose",
1378
1598
  exclude: false,
1379
1599
  maxModules: Infinity
1380
1600
  };
@@ -1391,6 +1611,7 @@ class Stats {
1391
1611
  optimizationBailout: true,
1392
1612
  errorDetails: true,
1393
1613
  publicPath: true,
1614
+ logging: true,
1394
1615
  exclude: false,
1395
1616
  maxModules: Infinity
1396
1617
  };
@@ -1400,19 +1621,22 @@ class Stats {
1400
1621
  modules: true,
1401
1622
  maxModules: 0,
1402
1623
  errors: true,
1403
- warnings: true
1624
+ warnings: true,
1625
+ logging: "warn"
1404
1626
  };
1405
1627
  case "errors-only":
1406
1628
  return {
1407
1629
  all: false,
1408
1630
  errors: true,
1409
- moduleTrace: true
1631
+ moduleTrace: true,
1632
+ logging: "error"
1410
1633
  };
1411
1634
  case "errors-warnings":
1412
1635
  return {
1413
1636
  all: false,
1414
1637
  errors: true,
1415
- warnings: true
1638
+ warnings: true,
1639
+ logging: "warn"
1416
1640
  };
1417
1641
  default:
1418
1642
  return {};
@@ -34,7 +34,11 @@ class SystemMainTemplatePlugin {
34
34
  const externals = chunk.getModules().filter(m => m.external);
35
35
 
36
36
  // The name this bundle should be registered as with System
37
- const name = this.name ? `${JSON.stringify(this.name)}, ` : "";
37
+ const name = this.name
38
+ ? `${JSON.stringify(
39
+ mainTemplate.getAssetPath(this.name, { hash, chunk })
40
+ )}, `
41
+ : "";
38
42
 
39
43
  // The array of dependencies that are external to webpack and will be provided by System
40
44
  const systemDependencies = JSON.stringify(