webpack 4.35.2 → 4.37.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.
@@ -14,25 +14,66 @@ const validateOptions = require("schema-utils");
14
14
  const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json");
15
15
 
16
16
  /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */
17
+ /** @typedef {import("./Chunk")} Chunk */
18
+ /** @typedef {import("webpack-sources").Source} Source */
19
+ /** @typedef {import("source-map").RawSourceMap} SourceMap */
20
+ /** @typedef {import("./Module")} Module */
21
+ /** @typedef {import("./Compilation")} Compilation */
22
+ /** @typedef {import("./Compiler")} Compiler */
23
+ /** @typedef {import("./Compilation")} SourceMapDefinition */
17
24
 
25
+ /**
26
+ * @typedef {object} SourceMapTask
27
+ * @property {Source} asset
28
+ * @property {Array<string | Module>} [modules]
29
+ * @property {string} source
30
+ * @property {string} file
31
+ * @property {SourceMap} sourceMap
32
+ * @property {Chunk} chunk
33
+ */
34
+
35
+ /**
36
+ * @param {string} name file path
37
+ * @returns {string} file name
38
+ */
18
39
  const basename = name => {
19
40
  if (!name.includes("/")) return name;
20
41
  return name.substr(name.lastIndexOf("/") + 1);
21
42
  };
22
43
 
44
+ /**
45
+ * @type {WeakMap<Source, {file: string, assets: {[k: string]: ConcatSource | RawSource}}>}
46
+ */
23
47
  const assetsCache = new WeakMap();
24
48
 
49
+ /**
50
+ * Creating {@link SourceMapTask} for given file
51
+ * @param {string} file current compiled file
52
+ * @param {Chunk} chunk related chunk
53
+ * @param {SourceMapDevToolPluginOptions} options source map options
54
+ * @param {Compilation} compilation compilation instance
55
+ * @returns {SourceMapTask | undefined} created task instance or `undefined`
56
+ */
25
57
  const getTaskForFile = (file, chunk, options, compilation) => {
26
58
  const asset = compilation.assets[file];
27
59
  const cache = assetsCache.get(asset);
60
+ /**
61
+ * If presented in cache, reassigns assets. Cache assets already have source maps.
62
+ */
28
63
  if (cache && cache.file === file) {
29
64
  for (const cachedFile in cache.assets) {
30
65
  compilation.assets[cachedFile] = cache.assets[cachedFile];
66
+ /**
67
+ * Add file to chunk, if not presented there
68
+ */
31
69
  if (cachedFile !== file) chunk.files.push(cachedFile);
32
70
  }
33
71
  return;
34
72
  }
35
73
  let source, sourceMap;
74
+ /**
75
+ * Check if asset can build source map
76
+ */
36
77
  if (asset.sourceAndMap) {
37
78
  const sourceAndMap = asset.sourceAndMap(options);
38
79
  sourceMap = sourceAndMap.map;
@@ -55,7 +96,8 @@ const getTaskForFile = (file, chunk, options, compilation) => {
55
96
 
56
97
  class SourceMapDevToolPlugin {
57
98
  /**
58
- * @param {SourceMapDevToolPluginOptions=} options options object
99
+ * @param {SourceMapDevToolPluginOptions} [options] options object
100
+ * @throws {Error} throws error, if got more than 1 arguments
59
101
  */
60
102
  constructor(options) {
61
103
  if (arguments.length > 1) {
@@ -68,21 +110,31 @@ class SourceMapDevToolPlugin {
68
110
 
69
111
  validateOptions(schema, options, "SourceMap DevTool Plugin");
70
112
 
113
+ /** @type {string | false} */
71
114
  this.sourceMapFilename = options.filename;
72
115
  /** @type {string | false} */
73
116
  this.sourceMappingURLComment =
74
117
  options.append === false
75
118
  ? false
76
119
  : options.append || "\n//# sourceMappingURL=[url]";
120
+ /** @type {string | Function} */
77
121
  this.moduleFilenameTemplate =
78
122
  options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]";
123
+ /** @type {string | Function} */
79
124
  this.fallbackModuleFilenameTemplate =
80
125
  options.fallbackModuleFilenameTemplate ||
81
126
  "webpack://[namespace]/[resourcePath]?[hash]";
127
+ /** @type {string} */
82
128
  this.namespace = options.namespace || "";
129
+ /** @type {SourceMapDevToolPluginOptions} */
83
130
  this.options = options;
84
131
  }
85
132
 
133
+ /**
134
+ * Apply compiler
135
+ * @param {Compiler} compiler compiler instance
136
+ * @returns {void}
137
+ */
86
138
  apply(compiler) {
87
139
  const sourceMapFilename = this.sourceMapFilename;
88
140
  const sourceMappingURLComment = this.sourceMappingURLComment;
@@ -102,12 +154,21 @@ class SourceMapDevToolPlugin {
102
154
  new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
103
155
 
104
156
  compilation.hooks.afterOptimizeChunkAssets.tap(
105
- {
106
- name: "SourceMapDevToolPlugin",
107
- context: true
108
- },
157
+ /** @type {TODO} */
158
+ ({ name: "SourceMapDevToolPlugin", context: true }),
159
+ /**
160
+ * @param {object} context hook context
161
+ * @param {Array<Chunk>} chunks resulted chunks
162
+ * @throws {Error} throws error, if `sourceMapFilename === false && sourceMappingURLComment === false`
163
+ * @returns {void}
164
+ */
109
165
  (context, chunks) => {
166
+ /** @type {Map<string | Module, string>} */
110
167
  const moduleToSourceNameMapping = new Map();
168
+ /**
169
+ * @type {Function}
170
+ * @returns {void}
171
+ */
111
172
  const reportProgress =
112
173
  context && context.reportProgress
113
174
  ? context.reportProgress
@@ -133,6 +194,7 @@ class SourceMapDevToolPlugin {
133
194
  file,
134
195
  "generate SourceMap"
135
196
  );
197
+ /** @type {SourceMapTask | undefined} */
136
198
  const task = getTaskForFile(file, chunk, options, compilation);
137
199
 
138
200
  if (task) {
@@ -165,10 +227,15 @@ class SourceMapDevToolPlugin {
165
227
  });
166
228
 
167
229
  reportProgress(0.5, "resolve sources");
230
+ /** @type {Set<string>} */
168
231
  const usedNamesSet = new Set(moduleToSourceNameMapping.values());
232
+ /** @type {Set<string>} */
169
233
  const conflictDetectionSet = new Set();
170
234
 
171
- // all modules in defined order (longest identifier first)
235
+ /**
236
+ * all modules in defined order (longest identifier first)
237
+ * @type {Array<string | Module>}
238
+ */
172
239
  const allModules = Array.from(moduleToSourceNameMapping.keys()).sort(
173
240
  (a, b) => {
174
241
  const ai = typeof a === "string" ? a : a.identifier();
@@ -254,7 +321,7 @@ class SourceMapDevToolPlugin {
254
321
  query = filename.substr(idx);
255
322
  filename = filename.substr(0, idx);
256
323
  }
257
- let sourceMapFile = compilation.getPath(sourceMapFilename, {
324
+ const pathParams = {
258
325
  chunk,
259
326
  filename: options.fileContext
260
327
  ? path.relative(options.fileContext, filename)
@@ -264,21 +331,31 @@ class SourceMapDevToolPlugin {
264
331
  contentHash: createHash("md4")
265
332
  .update(sourceMapString)
266
333
  .digest("hex")
267
- });
334
+ };
335
+ let sourceMapFile = compilation.getPath(
336
+ sourceMapFilename,
337
+ pathParams
338
+ );
268
339
  const sourceMapUrl = options.publicPath
269
340
  ? options.publicPath + sourceMapFile.replace(/\\/g, "/")
270
341
  : path
271
342
  .relative(path.dirname(file), sourceMapFile)
272
343
  .replace(/\\/g, "/");
344
+ /**
345
+ * Add source map url to compilation asset, if {@link currentSourceMappingURLComment} presented
346
+ */
273
347
  if (currentSourceMappingURLComment !== false) {
274
348
  assets[file] = compilation.assets[file] = new ConcatSource(
275
349
  new RawSource(source),
276
- currentSourceMappingURLComment.replace(
277
- /\[url\]/g,
278
- sourceMapUrl
350
+ compilation.getPath(
351
+ currentSourceMappingURLComment,
352
+ Object.assign({ url: sourceMapUrl }, pathParams)
279
353
  )
280
354
  );
281
355
  }
356
+ /**
357
+ * Add source map file to compilation assets and chunk files
358
+ */
282
359
  assets[sourceMapFile] = compilation.assets[
283
360
  sourceMapFile
284
361
  ] = new RawSource(sourceMapString);
@@ -289,6 +366,9 @@ class SourceMapDevToolPlugin {
289
366
  "SourceMapDevToolPlugin: append can't be false when no filename is provided"
290
367
  );
291
368
  }
369
+ /**
370
+ * Add source map as data url to asset
371
+ */
292
372
  assets[file] = compilation.assets[file] = new ConcatSource(
293
373
  new RawSource(source),
294
374
  currentSourceMappingURLComment
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,117 @@ 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.clear
759
+ ]);
760
+ collapsedGroups = true;
761
+ break;
762
+ }
763
+ for (const [origin, logEntries] of compilation.logging) {
764
+ const debugMode = loggingDebug.some(fn => fn(origin));
765
+ let collapseCounter = 0;
766
+ let processedLogEntries = logEntries;
767
+ if (!debugMode) {
768
+ processedLogEntries = processedLogEntries.filter(entry => {
769
+ if (!acceptedTypes.has(entry.type)) return false;
770
+ if (!collapsedGroups) {
771
+ switch (entry.type) {
772
+ case LogType.groupCollapsed:
773
+ collapseCounter++;
774
+ return collapseCounter === 1;
775
+ case LogType.group:
776
+ if (collapseCounter > 0) collapseCounter++;
777
+ return collapseCounter === 0;
778
+ case LogType.groupEnd:
779
+ if (collapseCounter > 0) {
780
+ collapseCounter--;
781
+ return false;
782
+ }
783
+ return true;
784
+ default:
785
+ return collapseCounter === 0;
786
+ }
787
+ }
788
+ return true;
789
+ });
790
+ }
791
+ processedLogEntries = processedLogEntries.map(entry => {
792
+ let message = undefined;
793
+ if (entry.type === LogType.time) {
794
+ message = `${entry.args[0]}: ${entry.args[1] * 1000 +
795
+ entry.args[2] / 1000000}ms`;
796
+ } else if (entry.args && entry.args.length > 0) {
797
+ message = util.format(entry.args[0], ...entry.args.slice(1));
798
+ }
799
+ return {
800
+ type:
801
+ (debugMode || collapsedGroups) &&
802
+ entry.type === LogType.groupCollapsed
803
+ ? LogType.group
804
+ : entry.type,
805
+ message,
806
+ trace: showLoggingTrace && entry.trace ? entry.trace : undefined
807
+ };
808
+ });
809
+ let name = identifierUtils
810
+ .makePathsRelative(context, origin, compilation.cache)
811
+ .replace(/\|/g, " ");
812
+ if (name in obj.logging) {
813
+ let i = 1;
814
+ while (`${name}#${i}` in obj.logging) {
815
+ i++;
816
+ }
817
+ name = `${name}#${i}`;
818
+ }
819
+ obj.logging[name] = {
820
+ entries: processedLogEntries,
821
+ filteredEntries: logEntries.length - processedLogEntries.length,
822
+ debug: debugMode
823
+ };
824
+ }
825
+ }
702
826
  if (showChildren) {
703
827
  obj.children = compilation.children.map((child, idx) => {
704
828
  const childOptions = Stats.getChildOptions(options, idx);
@@ -1305,6 +1429,95 @@ class Stats {
1305
1429
 
1306
1430
  processModulesList(obj, "");
1307
1431
 
1432
+ if (obj.logging) {
1433
+ for (const origin of Object.keys(obj.logging)) {
1434
+ const logData = obj.logging[origin];
1435
+ if (logData.entries.length > 0) {
1436
+ newline();
1437
+ if (logData.debug) {
1438
+ colors.red("DEBUG ");
1439
+ }
1440
+ colors.bold("LOG from " + origin);
1441
+ newline();
1442
+ let indent = "";
1443
+ for (const entry of logData.entries) {
1444
+ let color = colors.normal;
1445
+ let prefix = "";
1446
+ switch (entry.type) {
1447
+ case LogType.clear:
1448
+ colors.normal(`${indent}-------`);
1449
+ newline();
1450
+ continue;
1451
+ case LogType.error:
1452
+ color = colors.red;
1453
+ prefix = "<e> ";
1454
+ break;
1455
+ case LogType.warn:
1456
+ color = colors.yellow;
1457
+ prefix = "<w> ";
1458
+ break;
1459
+ case LogType.info:
1460
+ color = colors.green;
1461
+ prefix = "<i> ";
1462
+ break;
1463
+ case LogType.log:
1464
+ color = colors.bold;
1465
+ break;
1466
+ case LogType.trace:
1467
+ case LogType.debug:
1468
+ color = colors.normal;
1469
+ break;
1470
+ case LogType.profile:
1471
+ color = colors.magenta;
1472
+ prefix = "<p> ";
1473
+ break;
1474
+ case LogType.profileEnd:
1475
+ color = colors.magenta;
1476
+ prefix = "</p> ";
1477
+ break;
1478
+ case LogType.time:
1479
+ color = colors.magenta;
1480
+ prefix = "<t> ";
1481
+ break;
1482
+ case LogType.group:
1483
+ color = colors.cyan;
1484
+ break;
1485
+ case LogType.groupCollapsed:
1486
+ color = colors.cyan;
1487
+ prefix = "<+> ";
1488
+ break;
1489
+ case LogType.groupEnd:
1490
+ if (indent.length > 2)
1491
+ indent = indent.slice(0, indent.length - 2);
1492
+ continue;
1493
+ }
1494
+ if (entry.message) {
1495
+ for (const line of entry.message.split("\n")) {
1496
+ colors.normal(`${indent}${prefix}`);
1497
+ color(line);
1498
+ newline();
1499
+ }
1500
+ }
1501
+ if (entry.trace) {
1502
+ for (const line of entry.trace) {
1503
+ colors.normal(`${indent}| ${line}`);
1504
+ newline();
1505
+ }
1506
+ }
1507
+ switch (entry.type) {
1508
+ case LogType.group:
1509
+ indent += " ";
1510
+ break;
1511
+ }
1512
+ }
1513
+ if (logData.filteredEntries) {
1514
+ colors.normal(`+ ${logData.filteredEntries} hidden lines`);
1515
+ newline();
1516
+ }
1517
+ }
1518
+ }
1519
+ }
1520
+
1308
1521
  if (obj._showWarnings && obj.warnings) {
1309
1522
  for (const warning of obj.warnings) {
1310
1523
  newline();
@@ -1375,6 +1588,7 @@ class Stats {
1375
1588
  optimizationBailout: true,
1376
1589
  errorDetails: true,
1377
1590
  publicPath: true,
1591
+ logging: "verbose",
1378
1592
  exclude: false,
1379
1593
  maxModules: Infinity
1380
1594
  };
@@ -1391,6 +1605,7 @@ class Stats {
1391
1605
  optimizationBailout: true,
1392
1606
  errorDetails: true,
1393
1607
  publicPath: true,
1608
+ logging: true,
1394
1609
  exclude: false,
1395
1610
  maxModules: Infinity
1396
1611
  };
@@ -1400,19 +1615,22 @@ class Stats {
1400
1615
  modules: true,
1401
1616
  maxModules: 0,
1402
1617
  errors: true,
1403
- warnings: true
1618
+ warnings: true,
1619
+ logging: "warn"
1404
1620
  };
1405
1621
  case "errors-only":
1406
1622
  return {
1407
1623
  all: false,
1408
1624
  errors: true,
1409
- moduleTrace: true
1625
+ moduleTrace: true,
1626
+ logging: "error"
1410
1627
  };
1411
1628
  case "errors-warnings":
1412
1629
  return {
1413
1630
  all: false,
1414
1631
  errors: true,
1415
- warnings: true
1632
+ warnings: true,
1633
+ logging: "warn"
1416
1634
  };
1417
1635
  default:
1418
1636
  return {};
package/lib/Template.js CHANGED
@@ -49,7 +49,7 @@ const stringifyIdSortPredicate = (a, b) => {
49
49
  class Template {
50
50
  /**
51
51
  *
52
- * @param {Function} fn - a runtime function (.runtime.js) "template"
52
+ * @param {Function} fn a runtime function (.runtime.js) "template"
53
53
  * @returns {string} the updated and normalized function string
54
54
  */
55
55
  static getFunctionContent(fn) {
@@ -13,7 +13,8 @@ const REGEXP_HASH = /\[hash(?::(\d+))?\]/gi,
13
13
  REGEXP_MODULEID = /\[moduleid\]/gi,
14
14
  REGEXP_FILE = /\[file\]/gi,
15
15
  REGEXP_QUERY = /\[query\]/gi,
16
- REGEXP_FILEBASE = /\[filebase\]/gi;
16
+ REGEXP_FILEBASE = /\[filebase\]/gi,
17
+ REGEXP_URL = /\[url\]/gi;
17
18
 
18
19
  // Using global RegExp for .test is dangerous
19
20
  // We use a normal RegExp instead of .test
@@ -111,6 +112,8 @@ const replacePathVariables = (path, data) => {
111
112
  .replace(REGEXP_FILEBASE, getReplacer(data.basename))
112
113
  // query is optional, it's OK if it's in a path but there's nothing to replace it with
113
114
  .replace(REGEXP_QUERY, getReplacer(data.query, true))
115
+ // only available in sourceMappingURLComment
116
+ .replace(REGEXP_URL, getReplacer(data.url))
114
117
  );
115
118
  };
116
119
 
@@ -37,6 +37,8 @@ const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
37
37
  const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
38
38
  const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
39
39
 
40
+ const { cachedCleverMerge } = require("./util/cleverMerge");
41
+
40
42
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
41
43
  /** @typedef {import("./Compiler")} Compiler */
42
44
 
@@ -512,8 +514,7 @@ class WebpackOptionsApply extends OptionsApply {
512
514
  {
513
515
  fileSystem: compiler.inputFileSystem
514
516
  },
515
- options.resolve,
516
- resolveOptions
517
+ cachedCleverMerge(options.resolve, resolveOptions)
517
518
  );
518
519
  });
519
520
  compiler.resolverFactory.hooks.resolveOptions
@@ -524,8 +525,7 @@ class WebpackOptionsApply extends OptionsApply {
524
525
  fileSystem: compiler.inputFileSystem,
525
526
  resolveToContext: true
526
527
  },
527
- options.resolve,
528
- resolveOptions
528
+ cachedCleverMerge(options.resolve, resolveOptions)
529
529
  );
530
530
  });
531
531
  compiler.resolverFactory.hooks.resolveOptions
@@ -535,8 +535,7 @@ class WebpackOptionsApply extends OptionsApply {
535
535
  {
536
536
  fileSystem: compiler.inputFileSystem
537
537
  },
538
- options.resolveLoader,
539
- resolveOptions
538
+ cachedCleverMerge(options.resolveLoader, resolveOptions)
540
539
  );
541
540
  });
542
541
  compiler.hooks.afterResolvers.call(compiler);
@@ -363,6 +363,12 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
363
363
  options.resolveLoader.plugins.length > 0
364
364
  );
365
365
  });
366
+
367
+ this.set("infrastructureLogging", "call", value =>
368
+ Object.assign({}, value)
369
+ );
370
+ this.set("infrastructureLogging.level", "info");
371
+ this.set("infrastructureLogging.debug", false);
366
372
  }
367
373
  }
368
374
 
@@ -78,8 +78,8 @@ class Profiler {
78
78
  }
79
79
 
80
80
  /**
81
+ * an object that wraps Tracer and Profiler with a counter
81
82
  * @typedef {Object} Trace
82
- * @description an object that wraps Tracer and Profiler with a counter
83
83
  * @property {Tracer} trace instance of Tracer
84
84
  * @property {number} counter Counter
85
85
  * @property {Profiler} profiler instance of Profiler