webpack 4.23.1 → 4.26.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.
@@ -13,6 +13,10 @@ export interface DllPluginOptions {
13
13
  * If true, only entry points will be exposed
14
14
  */
15
15
  entryOnly?: boolean;
16
+ /**
17
+ * If true, manifest json file (output) will be formatted
18
+ */
19
+ format?: boolean;
16
20
  /**
17
21
  * Name of the exposed dll function (external name, use value of 'output.library')
18
22
  */
@@ -0,0 +1,42 @@
1
+ /**
2
+ * This file was automatically generated.
3
+ * DO NOT MODIFY BY HAND.
4
+ * Run `yarn special-lint-fix` to update
5
+ */
6
+
7
+ export type ProgressPluginArgument = ProgressPluginOptions | HandlerFunction;
8
+ /**
9
+ * Function that executes for every progress step
10
+ */
11
+ export type HandlerFunction = ((
12
+ percentage: number,
13
+ msg: string,
14
+ ...args: string[]
15
+ ) => void);
16
+
17
+ export interface ProgressPluginOptions {
18
+ /**
19
+ * Show active modules count and one active module in progress message
20
+ */
21
+ activeModules?: boolean;
22
+ /**
23
+ * Show entries count in progress message
24
+ */
25
+ entries?: boolean;
26
+ /**
27
+ * Function that executes for every progress step
28
+ */
29
+ handler?: HandlerFunction;
30
+ /**
31
+ * Show modules count in progress message
32
+ */
33
+ modules?: boolean;
34
+ /**
35
+ * Minimum modules count to start with. Only for mode=modules. Default: 500
36
+ */
37
+ modulesCount?: number;
38
+ /**
39
+ * Collect profile data for progress steps. Default: false
40
+ */
41
+ profile?: true | false | null;
42
+ }
@@ -29,11 +29,14 @@ class BasicEvaluatedExpression {
29
29
  this.regExp = null;
30
30
  this.string = null;
31
31
  this.quasis = null;
32
+ this.parts = null;
32
33
  this.array = null;
33
34
  this.items = null;
34
35
  this.options = null;
35
36
  this.prefix = null;
36
37
  this.postfix = null;
38
+ this.wrappedInnerExpressions = null;
39
+ this.expression = null;
37
40
  }
38
41
 
39
42
  isNull() {
@@ -105,10 +108,36 @@ class BasicEvaluatedExpression {
105
108
  : undefined;
106
109
  }
107
110
  if (this.isTemplateString()) {
108
- for (const quasi of this.quasis) {
109
- if (quasi.asBool()) return true;
111
+ const str = this.asString();
112
+ if (typeof str === "string") return str !== "";
113
+ }
114
+ return undefined;
115
+ }
116
+
117
+ asString() {
118
+ if (this.isBoolean()) return `${this.bool}`;
119
+ if (this.isNull()) return "null";
120
+ if (this.isString()) return this.string;
121
+ if (this.isNumber()) return `${this.number}`;
122
+ if (this.isRegExp()) return `${this.regExp}`;
123
+ if (this.isArray()) {
124
+ let array = [];
125
+ for (const item of this.items) {
126
+ const itemStr = item.asString();
127
+ if (itemStr === undefined) return undefined;
128
+ array.push(itemStr);
129
+ }
130
+ return `${array}`;
131
+ }
132
+ if (this.isConstArray()) return `${this.array}`;
133
+ if (this.isTemplateString()) {
134
+ let str = "";
135
+ for (const part of this.parts) {
136
+ const partStr = part.asString();
137
+ if (partStr === undefined) return undefined;
138
+ str += partStr;
110
139
  }
111
- // can't tell if string will be empty without executing
140
+ return str;
112
141
  }
113
142
  return undefined;
114
143
  }
@@ -148,10 +177,11 @@ class BasicEvaluatedExpression {
148
177
  return this;
149
178
  }
150
179
 
151
- setWrapped(prefix, postfix) {
180
+ setWrapped(prefix, postfix, innerExpressions) {
152
181
  this.type = TypeWrapped;
153
182
  this.prefix = prefix;
154
183
  this.postfix = postfix;
184
+ this.wrappedInnerExpressions = innerExpressions;
155
185
  return this;
156
186
  }
157
187
 
@@ -184,9 +214,11 @@ class BasicEvaluatedExpression {
184
214
  return this;
185
215
  }
186
216
 
187
- setTemplateString(quasis) {
217
+ setTemplateString(quasis, parts, kind) {
188
218
  this.type = TypeTemplateString;
189
219
  this.quasis = quasis;
220
+ this.parts = parts;
221
+ this.templateStringKind = kind;
190
222
  return this;
191
223
  }
192
224
 
@@ -206,6 +238,11 @@ class BasicEvaluatedExpression {
206
238
  this.range = range;
207
239
  return this;
208
240
  }
241
+
242
+ setExpression(expression) {
243
+ this.expression = expression;
244
+ return this;
245
+ }
209
246
  }
210
247
 
211
248
  module.exports = BasicEvaluatedExpression;
package/lib/Chunk.js CHANGED
@@ -430,7 +430,7 @@ class Chunk {
430
430
  }
431
431
 
432
432
  /**
433
- * @param {Chunk} newChunk the new chunk that will be split out of, and then chunk raphi twil=
433
+ * @param {Chunk} newChunk the new chunk that will be split out of the current chunk
434
434
  * @returns {void}
435
435
  */
436
436
  split(newChunk) {
@@ -224,6 +224,13 @@ class Compilation extends Tapable {
224
224
  /** @type {SyncHook<Module>} */
225
225
  succeedModule: new SyncHook(["module"]),
226
226
 
227
+ /** @type {SyncHook<Dependency, string>} */
228
+ addEntry: new SyncHook(["entry", "name"]),
229
+ /** @type {SyncHook<Dependency, string, Error>} */
230
+ failedEntry: new SyncHook(["entry", "name", "error"]),
231
+ /** @type {SyncHook<Dependency, string, Module>} */
232
+ succeedEntry: new SyncHook(["entry", "name", "module"]),
233
+
227
234
  /** @type {SyncWaterfallHook<DependencyReference, Dependency, Module>} */
228
235
  dependencyReference: new SyncWaterfallHook([
229
236
  "dependencyReference",
@@ -1041,6 +1048,8 @@ class Compilation extends Tapable {
1041
1048
  * @returns {void} returns
1042
1049
  */
1043
1050
  addEntry(context, entry, name, callback) {
1051
+ this.hooks.addEntry.call(entry, name);
1052
+
1044
1053
  const slot = {
1045
1054
  name: name,
1046
1055
  // TODO webpack 5 remove `request`
@@ -1068,6 +1077,7 @@ class Compilation extends Tapable {
1068
1077
  },
1069
1078
  (err, module) => {
1070
1079
  if (err) {
1080
+ this.hooks.failedEntry.call(entry, name, err);
1071
1081
  return callback(err);
1072
1082
  }
1073
1083
 
@@ -1079,6 +1089,7 @@ class Compilation extends Tapable {
1079
1089
  this._preparedEntrypoints.splice(idx, 1);
1080
1090
  }
1081
1091
  }
1092
+ this.hooks.succeedEntry.call(entry, name, module);
1082
1093
  return callback(null, module);
1083
1094
  }
1084
1095
  );
@@ -21,11 +21,15 @@ class RuntimeValue {
21
21
  }
22
22
 
23
23
  exec(parser) {
24
- for (const fileDependency of this.fileDependencies) {
25
- parser.state.module.buildInfo.fileDependencies.add(fileDependency);
24
+ if (this.fileDependencies === true) {
25
+ parser.state.module.buildInfo.cacheable = false;
26
+ } else {
27
+ for (const fileDependency of this.fileDependencies) {
28
+ parser.state.module.buildInfo.fileDependencies.add(fileDependency);
29
+ }
26
30
  }
27
31
 
28
- return this.fn();
32
+ return this.fn({ module: parser.state.module });
29
33
  }
30
34
  }
31
35
 
@@ -255,7 +255,7 @@ module.exports = class HotModuleReplacementPlugin {
255
255
  for (const key of Object.keys(records.chunkHashs)) {
256
256
  const chunkId = isNaN(+key) ? key : +key;
257
257
  const currentChunk = compilation.chunks.find(
258
- chunk => chunk.id === chunkId
258
+ chunk => `${chunk.id}` === key
259
259
  );
260
260
  if (currentChunk) {
261
261
  const newModules = currentChunk
@@ -67,7 +67,11 @@ class LibManifestPlugin {
67
67
  return obj;
68
68
  }, Object.create(null))
69
69
  };
70
- const content = Buffer.from(JSON.stringify(manifest), "utf8");
70
+ // Apply formatting to content if format flag is true;
71
+ const manifestContent = this.options.format
72
+ ? JSON.stringify(manifest, null, 2)
73
+ : JSON.stringify(manifest);
74
+ const content = Buffer.from(manifestContent, "utf8");
71
75
  compiler.outputFileSystem.mkdirp(path.dirname(targetPath), err => {
72
76
  if (err) return callback(err);
73
77
  compiler.outputFileSystem.writeFile(
package/lib/Parser.js CHANGED
@@ -216,62 +216,114 @@ class Parser extends Tapable {
216
216
  right.prefix &&
217
217
  right.prefix.isString()
218
218
  ) {
219
+ // "left" + ("prefix" + inner + "postfix")
220
+ // => ("leftprefix" + inner + "postfix")
219
221
  res.setWrapped(
220
222
  new BasicEvaluatedExpression()
221
223
  .setString(left.string + right.prefix.string)
222
224
  .setRange(joinRanges(left.range, right.prefix.range)),
223
- right.postfix
225
+ right.postfix,
226
+ right.wrappedInnerExpressions
224
227
  );
225
228
  } else if (right.isWrapped()) {
226
- res.setWrapped(
227
- new BasicEvaluatedExpression()
228
- .setString(left.string)
229
- .setRange(left.range),
230
- right.postfix
231
- );
229
+ // "left" + ([null] + inner + "postfix")
230
+ // => ("left" + inner + "postfix")
231
+ res.setWrapped(left, right.postfix, right.wrappedInnerExpressions);
232
232
  } else {
233
- res.setWrapped(left, null);
233
+ // "left" + expr
234
+ // => ("left" + expr + "")
235
+ res.setWrapped(left, null, [right]);
234
236
  }
235
237
  } else if (left.isNumber()) {
236
238
  if (right.isString()) {
237
239
  res.setString(left.number + right.string);
238
240
  } else if (right.isNumber()) {
239
241
  res.setNumber(left.number + right.number);
242
+ } else {
243
+ return;
240
244
  }
241
245
  } else if (left.isWrapped()) {
242
246
  if (left.postfix && left.postfix.isString() && right.isString()) {
247
+ // ("prefix" + inner + "postfix") + "right"
248
+ // => ("prefix" + inner + "postfixright")
243
249
  res.setWrapped(
244
250
  left.prefix,
245
251
  new BasicEvaluatedExpression()
246
252
  .setString(left.postfix.string + right.string)
247
- .setRange(joinRanges(left.postfix.range, right.range))
253
+ .setRange(joinRanges(left.postfix.range, right.range)),
254
+ left.wrappedInnerExpressions
248
255
  );
249
256
  } else if (
250
257
  left.postfix &&
251
258
  left.postfix.isString() &&
252
259
  right.isNumber()
253
260
  ) {
261
+ // ("prefix" + inner + "postfix") + 123
262
+ // => ("prefix" + inner + "postfix123")
254
263
  res.setWrapped(
255
264
  left.prefix,
256
265
  new BasicEvaluatedExpression()
257
266
  .setString(left.postfix.string + right.number)
258
- .setRange(joinRanges(left.postfix.range, right.range))
267
+ .setRange(joinRanges(left.postfix.range, right.range)),
268
+ left.wrappedInnerExpressions
259
269
  );
260
270
  } else if (right.isString()) {
261
- res.setWrapped(left.prefix, right);
271
+ // ("prefix" + inner + [null]) + "right"
272
+ // => ("prefix" + inner + "right")
273
+ res.setWrapped(left.prefix, right, left.wrappedInnerExpressions);
262
274
  } else if (right.isNumber()) {
275
+ // ("prefix" + inner + [null]) + 123
276
+ // => ("prefix" + inner + "123")
263
277
  res.setWrapped(
264
278
  left.prefix,
265
279
  new BasicEvaluatedExpression()
266
280
  .setString(right.number + "")
267
- .setRange(right.range)
281
+ .setRange(right.range),
282
+ left.wrappedInnerExpressions
283
+ );
284
+ } else if (right.isWrapped()) {
285
+ // ("prefix1" + inner1 + "postfix1") + ("prefix2" + inner2 + "postfix2")
286
+ // ("prefix1" + inner1 + "postfix1" + "prefix2" + inner2 + "postfix2")
287
+ res.setWrapped(
288
+ left.prefix,
289
+ right.postfix,
290
+ left.wrappedInnerExpressions &&
291
+ right.wrappedInnerExpressions &&
292
+ left.wrappedInnerExpressions
293
+ .concat(left.postfix ? [left.postfix] : [])
294
+ .concat(right.prefix ? [right.prefix] : [])
295
+ .concat(right.wrappedInnerExpressions)
268
296
  );
269
297
  } else {
270
- res.setWrapped(left.prefix, new BasicEvaluatedExpression());
298
+ // ("prefix" + inner + postfix) + expr
299
+ // => ("prefix" + inner + postfix + expr + [null])
300
+ res.setWrapped(
301
+ left.prefix,
302
+ null,
303
+ left.wrappedInnerExpressions &&
304
+ left.wrappedInnerExpressions.concat(
305
+ left.postfix ? [left.postfix, right] : [right]
306
+ )
307
+ );
271
308
  }
272
309
  } else {
273
310
  if (right.isString()) {
274
- res.setWrapped(null, right);
311
+ // left + "right"
312
+ // => ([null] + left + "right")
313
+ res.setWrapped(null, right, [left]);
314
+ } else if (right.isWrapped()) {
315
+ // left + (prefix + inner + "postfix")
316
+ // => ([null] + left + prefix + inner + "postfix")
317
+ res.setWrapped(
318
+ null,
319
+ right.postfix,
320
+ right.wrappedInnerExpressions &&
321
+ (right.prefix ? [left, right.prefix] : [left]).concat(
322
+ right.wrappedInnerExpressions
323
+ )
324
+ );
325
+ } else {
326
+ return;
275
327
  }
276
328
  }
277
329
  res.setRange(expr.range);
@@ -602,62 +654,66 @@ class Parser extends Tapable {
602
654
 
603
655
  /**
604
656
  * @param {string} kind "cooked" | "raw"
605
- * @param {TODO[]} quasis quasis
606
- * @param {TODO[]} expressions expressions
607
- * @returns {BasicEvaluatedExpression[]} Simplified template
657
+ * @param {TODO} templateLiteralExpr TemplateLiteral expr
658
+ * @returns {{quasis: BasicEvaluatedExpression[], parts: BasicEvaluatedExpression[]}} Simplified template
608
659
  */
609
- const getSimplifiedTemplateResult = (kind, quasis, expressions) => {
660
+ const getSimplifiedTemplateResult = (kind, templateLiteralExpr) => {
661
+ const quasis = [];
610
662
  const parts = [];
611
663
 
612
- for (let i = 0; i < quasis.length; i++) {
613
- parts.push(
614
- new BasicEvaluatedExpression()
615
- .setString(quasis[i].value[kind])
616
- .setRange(quasis[i].range)
617
- );
664
+ for (let i = 0; i < templateLiteralExpr.quasis.length; i++) {
665
+ const quasiExpr = templateLiteralExpr.quasis[i];
666
+ const quasi = quasiExpr.value[kind];
618
667
 
619
668
  if (i > 0) {
620
- const prevExpr = parts[parts.length - 2],
621
- lastExpr = parts[parts.length - 1];
622
- const expr = this.evaluateExpression(expressions[i - 1]);
623
- if (!(expr.isString() || expr.isNumber())) continue;
624
-
625
- prevExpr.setString(
626
- prevExpr.string +
627
- (expr.isString() ? expr.string : expr.number) +
628
- lastExpr.string
669
+ const prevExpr = parts[parts.length - 1];
670
+ const expr = this.evaluateExpression(
671
+ templateLiteralExpr.expressions[i - 1]
629
672
  );
630
- prevExpr.setRange([prevExpr.range[0], lastExpr.range[1]]);
631
- parts.pop();
673
+ const exprAsString = expr.asString();
674
+ if (typeof exprAsString === "string") {
675
+ // We can merge quasi + expr + quasi when expr
676
+ // is a const string
677
+
678
+ prevExpr.setString(prevExpr.string + exprAsString + quasi);
679
+ prevExpr.setRange([prevExpr.range[0], quasiExpr.range[1]]);
680
+ // We unset the expression as it doesn't match to a single expression
681
+ prevExpr.setExpression(undefined);
682
+ continue;
683
+ }
684
+ parts.push(expr);
632
685
  }
686
+
687
+ const part = new BasicEvaluatedExpression()
688
+ .setString(quasi)
689
+ .setRange(quasiExpr.range)
690
+ .setExpression(quasiExpr);
691
+ quasis.push(part);
692
+ parts.push(part);
633
693
  }
634
- return parts;
694
+ return {
695
+ quasis,
696
+ parts
697
+ };
635
698
  };
636
699
 
637
700
  this.hooks.evaluate.for("TemplateLiteral").tap("Parser", node => {
638
- const parts = getSimplifiedTemplateResult.call(
639
- this,
640
- "cooked",
641
- node.quasis,
642
- node.expressions
643
- );
701
+ const { quasis, parts } = getSimplifiedTemplateResult("cooked", node);
644
702
  if (parts.length === 1) {
645
703
  return parts[0].setRange(node.range);
646
704
  }
647
705
  return new BasicEvaluatedExpression()
648
- .setTemplateString(parts)
706
+ .setTemplateString(quasis, parts, "cooked")
649
707
  .setRange(node.range);
650
708
  });
651
709
  this.hooks.evaluate.for("TaggedTemplateExpression").tap("Parser", node => {
652
710
  if (this.evaluateExpression(node.tag).identifier !== "String.raw") return;
653
- const parts = getSimplifiedTemplateResult.call(
654
- this,
655
- "raw",
656
- node.quasi.quasis,
657
- node.quasi.expressions
658
- );
711
+ const { quasis, parts } = getSimplifiedTemplateResult("raw", node.quasi);
712
+ if (parts.length === 1) {
713
+ return parts[0].setRange(node.range);
714
+ }
659
715
  return new BasicEvaluatedExpression()
660
- .setTemplateString(parts)
716
+ .setTemplateString(quasis, parts, "raw")
661
717
  .setRange(node.range);
662
718
  });
663
719
 
@@ -1926,13 +1982,20 @@ class Parser extends Tapable {
1926
1982
  const hook = this.hooks.evaluate.get(expression.type);
1927
1983
  if (hook !== undefined) {
1928
1984
  const result = hook.call(expression);
1929
- if (result !== undefined) return result;
1985
+ if (result !== undefined) {
1986
+ if (result) {
1987
+ result.setExpression(expression);
1988
+ }
1989
+ return result;
1990
+ }
1930
1991
  }
1931
1992
  } catch (e) {
1932
1993
  console.warn(e);
1933
1994
  // ignore error
1934
1995
  }
1935
- return new BasicEvaluatedExpression().setRange(expression.range);
1996
+ return new BasicEvaluatedExpression()
1997
+ .setRange(expression.range)
1998
+ .setExpression(expression);
1936
1999
  }
1937
2000
 
1938
2001
  parseString(expression) {
@@ -4,8 +4,15 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ const validateOptions = require("schema-utils");
8
+ const schema = require("../schemas/plugins/ProgressPlugin.json");
9
+
10
+ /** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginArgument} ProgressPluginArgument */
11
+ /** @typedef {import("../declarations/plugins/ProgressPlugin").ProgressPluginOptions} ProgressPluginOptions */
12
+
7
13
  const createDefaultHandler = profile => {
8
14
  let lineCaretPosition = 0;
15
+ let lastMessage = "";
9
16
  let lastState;
10
17
  let lastStateTime;
11
18
 
@@ -46,8 +53,11 @@ const createDefaultHandler = profile => {
46
53
  lastStateTime = now;
47
54
  }
48
55
  }
49
- goToLineStart(msg);
50
- process.stderr.write(msg);
56
+ if (lastMessage !== msg) {
57
+ goToLineStart(msg);
58
+ process.stderr.write(msg);
59
+ lastMessage = msg;
60
+ }
51
61
  };
52
62
 
53
63
  const goToLineStart = nextMessage => {
@@ -66,19 +76,34 @@ const createDefaultHandler = profile => {
66
76
  };
67
77
 
68
78
  class ProgressPlugin {
79
+ /**
80
+ * @param {ProgressPluginArgument} options options
81
+ */
69
82
  constructor(options) {
70
83
  if (typeof options === "function") {
71
84
  options = {
72
85
  handler: options
73
86
  };
74
87
  }
88
+
75
89
  options = options || {};
90
+ validateOptions(schema, options, "Progress Plugin");
91
+ options = Object.assign({}, ProgressPlugin.defaultOptions, options);
92
+
76
93
  this.profile = options.profile;
77
94
  this.handler = options.handler;
95
+ this.modulesCount = options.modulesCount;
96
+ this.showEntries = options.entries;
97
+ this.showModules = options.modules;
98
+ this.showActiveModules = options.activeModules;
78
99
  }
79
100
 
80
101
  apply(compiler) {
102
+ const { modulesCount } = this;
81
103
  const handler = this.handler || createDefaultHandler(this.profile);
104
+ const showEntries = this.showEntries;
105
+ const showModules = this.showModules;
106
+ const showActiveModules = this.showActiveModules;
82
107
  if (compiler.compilers) {
83
108
  const states = new Array(compiler.compilers.length);
84
109
  compiler.compilers.forEach((compiler, idx) => {
@@ -95,48 +120,97 @@ class ProgressPlugin {
95
120
  });
96
121
  } else {
97
122
  let lastModulesCount = 0;
98
- let moduleCount = 500;
123
+ let lastEntriesCount = 0;
124
+ let moduleCount = modulesCount;
125
+ let entriesCount = 1;
99
126
  let doneModules = 0;
100
- const activeModules = [];
101
-
102
- const update = module => {
103
- handler(
104
- 0.1 + (doneModules / Math.max(lastModulesCount, moduleCount)) * 0.6,
105
- "building modules",
106
- `${doneModules}/${moduleCount} modules`,
107
- `${activeModules.length} active`,
108
- activeModules[activeModules.length - 1]
109
- );
127
+ let doneEntries = 0;
128
+ const activeModules = new Set();
129
+ let lastActiveModule = "";
130
+
131
+ const update = () => {
132
+ const percentByModules =
133
+ doneModules / Math.max(lastModulesCount, moduleCount);
134
+ const percentByEntries =
135
+ doneEntries / Math.max(lastEntriesCount, entriesCount);
136
+
137
+ const items = [
138
+ 0.1 + Math.max(percentByModules, percentByEntries) * 0.6,
139
+ "building"
140
+ ];
141
+ if (showEntries) {
142
+ items.push(`${doneEntries}/${entriesCount} entries`);
143
+ }
144
+ if (showModules) {
145
+ items.push(`${doneModules}/${moduleCount} modules`);
146
+ }
147
+ if (showActiveModules) {
148
+ items.push(`${activeModules.size} active`);
149
+ items.push(lastActiveModule);
150
+ }
151
+ handler(...items);
152
+ };
153
+
154
+ const moduleAdd = module => {
155
+ moduleCount++;
156
+ if (showActiveModules) {
157
+ const ident = module.identifier();
158
+ if (ident) {
159
+ activeModules.add(ident);
160
+ lastActiveModule = ident;
161
+ }
162
+ }
163
+ update();
164
+ };
165
+
166
+ const entryAdd = (entry, name) => {
167
+ entriesCount++;
168
+ update();
110
169
  };
111
170
 
112
171
  const moduleDone = module => {
113
172
  doneModules++;
114
- const ident = module.identifier();
115
- if (ident) {
116
- const idx = activeModules.indexOf(ident);
117
- if (idx >= 0) activeModules.splice(idx, 1);
173
+ if (showActiveModules) {
174
+ const ident = module.identifier();
175
+ if (ident) {
176
+ activeModules.delete(ident);
177
+ if (lastActiveModule === ident) {
178
+ lastActiveModule = "";
179
+ for (const m of activeModules) {
180
+ lastActiveModule = m;
181
+ }
182
+ }
183
+ }
118
184
  }
119
185
  update();
120
186
  };
187
+
188
+ const entryDone = (entry, name) => {
189
+ doneEntries++;
190
+ update();
191
+ };
192
+
121
193
  compiler.hooks.compilation.tap("ProgressPlugin", compilation => {
122
194
  if (compilation.compiler.isChild()) return;
123
195
  lastModulesCount = moduleCount;
124
- moduleCount = 0;
125
- doneModules = 0;
196
+ lastEntriesCount = entriesCount;
197
+ moduleCount = entriesCount = 0;
198
+ doneModules = doneEntries = 0;
126
199
  handler(0, "compiling");
127
- compilation.hooks.buildModule.tap("ProgressPlugin", module => {
128
- moduleCount++;
129
- const ident = module.identifier();
130
- if (ident) {
131
- activeModules.push(ident);
132
- }
133
- update();
134
- });
200
+
201
+ compilation.hooks.buildModule.tap("ProgressPlugin", moduleAdd);
135
202
  compilation.hooks.failedModule.tap("ProgressPlugin", moduleDone);
136
203
  compilation.hooks.succeedModule.tap("ProgressPlugin", moduleDone);
204
+
205
+ compilation.hooks.addEntry.tap("ProgressPlugin", entryAdd);
206
+ compilation.hooks.failedEntry.tap("ProgressPlugin", entryDone);
207
+ compilation.hooks.succeedEntry.tap("ProgressPlugin", entryDone);
208
+
137
209
  const hooks = {
138
210
  finishModules: "finish module graph",
139
211
  seal: "sealing",
212
+ beforeChunks: "chunk graph",
213
+ afterChunks: "after chunk graph",
140
214
  optimizeDependenciesBasic: "basic dependencies optimization",
141
215
  optimizeDependencies: "dependencies optimization",
142
216
  optimizeDependenciesAdvanced: "advanced dependencies optimization",
@@ -171,6 +245,7 @@ class ProgressPlugin {
171
245
  recordModules: "record modules",
172
246
  recordChunks: "record chunks",
173
247
  beforeHash: "hashing",
248
+ contentHash: "content hashing",
174
249
  afterHash: "after hashing",
175
250
  recordHash: "record hash",
176
251
  beforeModuleAssets: "module assets processing",
@@ -243,4 +318,14 @@ class ProgressPlugin {
243
318
  }
244
319
  }
245
320
  }
321
+
322
+ ProgressPlugin.defaultOptions = {
323
+ profile: false,
324
+ modulesCount: 500,
325
+ modules: true,
326
+ activeModules: true,
327
+ // TODO webpack 5 default this to true
328
+ entries: false
329
+ };
330
+
246
331
  module.exports = ProgressPlugin;
@@ -76,9 +76,8 @@ class ProvidePlugin {
76
76
  normalModuleFactory.hooks.parser
77
77
  .for("javascript/dynamic")
78
78
  .tap("ProvidePlugin", handler);
79
- normalModuleFactory.hooks.parser
80
- .for("javascript/esm")
81
- .tap("ProvidePlugin", handler);
79
+
80
+ // Disable ProvidePlugin for javascript/esm, see https://github.com/webpack/webpack/issues/7032
82
81
  }
83
82
  );
84
83
  }
@@ -302,10 +302,10 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
302
302
  this.set("optimization.minimizer", "make", options => [
303
303
  {
304
304
  apply: compiler => {
305
- // Lazy load the uglifyjs plugin
306
- const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
305
+ // Lazy load the Terser plugin
306
+ const TerserPlugin = require("terser-webpack-plugin");
307
307
  const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
308
- new UglifyJsPlugin({
308
+ new TerserPlugin({
309
309
  cache: true,
310
310
  parallel: true,
311
311
  sourceMap:
@@ -136,7 +136,9 @@ class AMDDefineDependencyParserPlugin {
136
136
  param.range,
137
137
  param,
138
138
  expr,
139
- this.options
139
+ this.options,
140
+ {},
141
+ parser
140
142
  );
141
143
  if (!dep) return;
142
144
  dep.loc = expr.loc;
@@ -142,7 +142,9 @@ class AMDRequireDependenciesBlockParserPlugin {
142
142
  param.range,
143
143
  param,
144
144
  expr,
145
- this.options
145
+ this.options,
146
+ {},
147
+ parser
146
148
  );
147
149
  if (!dep) return;
148
150
  dep.loc = expr.loc;
@@ -35,7 +35,9 @@ class CommonJsRequireDependencyParserPlugin {
35
35
  expr.range,
36
36
  param,
37
37
  expr,
38
- options
38
+ options,
39
+ {},
40
+ parser
39
41
  );
40
42
  if (!dep) return;
41
43
  dep.loc = expr.loc;
@@ -47,7 +47,9 @@ ContextDependencyHelpers.create = (
47
47
  param,
48
48
  expr,
49
49
  options,
50
- contextOptions
50
+ contextOptions,
51
+ // when parser is not passed in, expressions won't be walked
52
+ parser = null
51
53
  ) => {
52
54
  if (param.isTemplateString()) {
53
55
  let prefixRaw = param.quasis[0].string;
@@ -55,19 +57,30 @@ ContextDependencyHelpers.create = (
55
57
  param.quasis.length > 1
56
58
  ? param.quasis[param.quasis.length - 1].string
57
59
  : "";
58
- const prefixRange = [param.quasis[0].range[0], param.quasis[0].range[1]];
59
- const postfixRange =
60
- param.quasis.length > 1
61
- ? param.quasis[param.quasis.length - 1].range
62
- : "";
60
+
63
61
  const valueRange = param.range;
64
62
  const { context, prefix } = splitContextFromPrefix(prefixRaw);
65
63
  const { postfix, query } = splitQueryFromPostfix(postfixRaw);
66
- // If there are more than two quasis, maybe the generated RegExp can be more precise?
64
+
65
+ // When there are more than two quasis, the generated RegExp can be more precise
66
+ // We join the quasis with the expression regexp
67
+ const innerQuasis = param.quasis.slice(1, param.quasis.length - 1);
68
+ const innerRegExp =
69
+ options.wrappedContextRegExp.source +
70
+ innerQuasis
71
+ .map(q => quotemeta(q.string) + options.wrappedContextRegExp.source)
72
+ .join("");
73
+
74
+ // Example: `./context/pre${e}inner${e}inner2${e}post?query`
75
+ // context: "./context"
76
+ // prefix: "./pre"
77
+ // innerQuasis: [BEE("inner"), BEE("inner2")]
78
+ // (BEE = BasicEvaluatedExpression)
79
+ // postfix: "post"
80
+ // query: "?query"
81
+ // regExp: /^\.\/pre.*inner.*inner2.*post$/
67
82
  const regExp = new RegExp(
68
- `^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(
69
- postfix
70
- )}$`
83
+ `^${quotemeta(prefix)}${innerRegExp}${quotemeta(postfix)}$`
71
84
  );
72
85
  const dep = new Dep(
73
86
  Object.assign(
@@ -84,18 +97,48 @@ ContextDependencyHelpers.create = (
84
97
  );
85
98
  dep.loc = expr.loc;
86
99
  const replaces = [];
87
- if (prefixRange && prefix !== prefixRaw) {
88
- replaces.push({
89
- range: prefixRange,
90
- value: prefix
91
- });
92
- }
93
- if (postfixRange && postfix !== postfixRaw) {
94
- replaces.push({
95
- range: postfixRange,
96
- value: postfix
97
- });
98
- }
100
+
101
+ param.parts.forEach((part, i) => {
102
+ if (i % 2 === 0) {
103
+ // Quasis or merged quasi
104
+ let range = part.range;
105
+ let value = part.string;
106
+ if (param.templateStringKind === "cooked") {
107
+ value = JSON.stringify(value);
108
+ value = value.slice(1, value.length - 1);
109
+ }
110
+ if (i === 0) {
111
+ // prefix
112
+ value = prefix;
113
+ range = [param.range[0], part.range[1]];
114
+ value =
115
+ (param.templateStringKind === "cooked" ? "`" : "String.raw`") +
116
+ value;
117
+ } else if (i === param.parts.length - 1) {
118
+ // postfix
119
+ value = postfix;
120
+ range = [part.range[0], param.range[1]];
121
+ value = value + "`";
122
+ } else if (
123
+ part.expression &&
124
+ part.expression.type === "TemplateElement" &&
125
+ part.expression.value.raw === value
126
+ ) {
127
+ // Shortcut when it's a single quasi and doesn't need to be replaced
128
+ return;
129
+ }
130
+ replaces.push({
131
+ range,
132
+ value
133
+ });
134
+ } else {
135
+ // Expression
136
+ if (parser) {
137
+ parser.walkExpression(part.expression);
138
+ }
139
+ }
140
+ });
141
+
99
142
  dep.replaces = replaces;
100
143
  dep.critical =
101
144
  options.wrappedContextCritical &&
@@ -137,13 +180,13 @@ ContextDependencyHelpers.create = (
137
180
  );
138
181
  dep.loc = expr.loc;
139
182
  const replaces = [];
140
- if (prefixRange && prefix !== prefixRaw) {
183
+ if (prefixRange) {
141
184
  replaces.push({
142
185
  range: prefixRange,
143
186
  value: JSON.stringify(prefix)
144
187
  });
145
188
  }
146
- if (postfixRange && postfix !== postfixRaw) {
189
+ if (postfixRange) {
147
190
  replaces.push({
148
191
  range: postfixRange,
149
192
  value: JSON.stringify(postfix)
@@ -153,6 +196,13 @@ ContextDependencyHelpers.create = (
153
196
  dep.critical =
154
197
  options.wrappedContextCritical &&
155
198
  "a part of the request of a dependency is an expression";
199
+
200
+ if (parser && param.wrappedInnerExpressions) {
201
+ for (const part of param.wrappedInnerExpressions) {
202
+ if (part.expression) parser.walkExpression(part.expression);
203
+ }
204
+ }
205
+
156
206
  return dep;
157
207
  } else {
158
208
  const dep = new Dep(
@@ -172,6 +222,11 @@ ContextDependencyHelpers.create = (
172
222
  dep.critical =
173
223
  options.exprContextCritical &&
174
224
  "the request of a dependency is an expression";
225
+
226
+ if (parser) {
227
+ parser.walkExpression(param.expression);
228
+ }
229
+
175
230
  return dep;
176
231
  }
177
232
  };
@@ -248,7 +248,8 @@ class ImportParserPlugin {
248
248
  namespaceObject: parser.state.module.buildMeta.strictHarmonyModule
249
249
  ? "strict"
250
250
  : true
251
- }
251
+ },
252
+ parser
252
253
  );
253
254
  if (!dep) return;
254
255
  dep.loc = expr.loc;
@@ -61,7 +61,8 @@ class RequireResolveDependencyParserPlugin {
61
61
  options,
62
62
  {
63
63
  mode: weak ? "weak" : "sync"
64
- }
64
+ },
65
+ parser
65
66
  );
66
67
  if (!dep) return;
67
68
  dep.loc = expr.loc;
@@ -7,7 +7,7 @@
7
7
  const ExternalsPlugin = require("../ExternalsPlugin");
8
8
 
9
9
  const builtins =
10
- // eslint-disable-next-line node/no-unsupported-features/node-builtins
10
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins,node/no-deprecated-api
11
11
  require("module").builtinModules || Object.keys(process.binding("natives"));
12
12
 
13
13
  class NodeTargetPlugin {
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "4.23.1",
3
+ "version": "4.26.0",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
6
6
  "license": "MIT",
7
7
  "dependencies": {
8
- "@webassemblyjs/ast": "1.7.10",
9
- "@webassemblyjs/helper-module-context": "1.7.10",
10
- "@webassemblyjs/wasm-edit": "1.7.10",
11
- "@webassemblyjs/wasm-parser": "1.7.10",
8
+ "@webassemblyjs/ast": "1.7.11",
9
+ "@webassemblyjs/helper-module-context": "1.7.11",
10
+ "@webassemblyjs/wasm-edit": "1.7.11",
11
+ "@webassemblyjs/wasm-parser": "1.7.11",
12
12
  "acorn": "^5.6.2",
13
13
  "acorn-dynamic-import": "^3.0.0",
14
14
  "ajv": "^6.1.0",
@@ -26,7 +26,7 @@
26
26
  "node-libs-browser": "^2.0.0",
27
27
  "schema-utils": "^0.4.4",
28
28
  "tapable": "^1.1.0",
29
- "uglifyjs-webpack-plugin": "^1.2.4",
29
+ "terser-webpack-plugin": "^1.1.0",
30
30
  "watchpack": "^1.5.0",
31
31
  "webpack-sources": "^1.3.0"
32
32
  },
@@ -42,27 +42,28 @@
42
42
  "coveralls": "^3.0.2",
43
43
  "css-loader": "^0.28.3",
44
44
  "es6-promise-polyfill": "^1.1.1",
45
- "eslint": "^5.2.0",
46
- "eslint-config-prettier": "^2.9.0",
47
- "eslint-plugin-jest": "^21.18.0",
48
- "eslint-plugin-node": "^7.0.1",
49
- "eslint-plugin-prettier": "^2.6.2",
45
+ "eslint": "^5.8.0",
46
+ "eslint-config-prettier": "^3.1.0",
47
+ "eslint-plugin-jest": "^21.26.2",
48
+ "eslint-plugin-node": "^8.0.0",
49
+ "eslint-plugin-prettier": "^3.0.0",
50
50
  "express": "~4.13.1",
51
51
  "file-loader": "^1.1.6",
52
- "glob": "^7.1.2",
53
- "husky": "^1.0.0-rc.6",
52
+ "glob": "^7.1.3",
53
+ "husky": "^1.1.3",
54
54
  "i18n-webpack-plugin": "^1.0.0",
55
55
  "istanbul": "^0.4.5",
56
56
  "jade": "^1.11.0",
57
57
  "jade-loader": "~0.8.0",
58
58
  "jest": "24.0.0-alpha.1",
59
+ "jest-junit": "^5.2.0",
59
60
  "json-loader": "^0.5.7",
60
61
  "json-schema-to-typescript": "^6.0.1",
61
62
  "less": "^2.5.1",
62
63
  "less-loader": "^4.0.3",
63
- "lint-staged": "^7.2.0",
64
+ "lint-staged": "^8.0.4",
64
65
  "lodash": "^4.17.4",
65
- "prettier": "^1.14.0",
66
+ "prettier": "^1.14.3",
66
67
  "pug": "^2.0.3",
67
68
  "pug-loader": "^2.4.0",
68
69
  "raw-loader": "~0.5.0",
@@ -12,6 +12,10 @@
12
12
  "description": "If true, only entry points will be exposed",
13
13
  "type": "boolean"
14
14
  },
15
+ "format": {
16
+ "description": "If true, manifest json file (output) will be formatted",
17
+ "type": "boolean"
18
+ },
15
19
  "name": {
16
20
  "description": "Name of the exposed dll function (external name, use value of 'output.library')",
17
21
  "type": "string",
@@ -0,0 +1,52 @@
1
+ {
2
+ "definitions": {
3
+ "HandlerFunction": {
4
+ "description": "Function that executes for every progress step",
5
+ "instanceof": "Function",
6
+ "tsType": "((percentage: number, msg: string, ...args: string[]) => void)"
7
+ },
8
+ "ProgressPluginOptions": {
9
+ "type": "object",
10
+ "additionalProperties": false,
11
+ "properties": {
12
+ "activeModules": {
13
+ "description": "Show active modules count and one active module in progress message",
14
+ "type": "boolean"
15
+ },
16
+ "entries": {
17
+ "description": "Show entries count in progress message",
18
+ "type": "boolean"
19
+ },
20
+ "handler": {
21
+ "description": "Function that executes for every progress step",
22
+ "anyOf": [
23
+ {
24
+ "$ref": "#/definitions/HandlerFunction"
25
+ }
26
+ ]
27
+ },
28
+ "modules": {
29
+ "description": "Show modules count in progress message",
30
+ "type": "boolean"
31
+ },
32
+ "modulesCount": {
33
+ "description": "Minimum modules count to start with. Only for mode=modules. Default: 500",
34
+ "type": "number"
35
+ },
36
+ "profile": {
37
+ "description": "Collect profile data for progress steps. Default: false",
38
+ "enum": [true, false, null]
39
+ }
40
+ }
41
+ }
42
+ },
43
+ "title": "ProgressPluginArgument",
44
+ "oneOf": [
45
+ {
46
+ "$ref": "#/definitions/ProgressPluginOptions"
47
+ },
48
+ {
49
+ "$ref": "#/definitions/HandlerFunction"
50
+ }
51
+ ]
52
+ }