webpack 4.34.0 → 4.35.3

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.
@@ -558,6 +558,10 @@ export interface RuleSetRule {
558
558
  * Shortcut for use.query
559
559
  */
560
560
  query?: RuleSetQuery;
561
+ /**
562
+ * Match rules with custom resource name
563
+ */
564
+ realResource?: RuleSetConditionOrConditionsAbsolute;
561
565
  /**
562
566
  * Options for the resolver
563
567
  */
@@ -870,6 +874,10 @@ export interface OptimizationSplitChunksOptions {
870
874
  * Sets the name delimiter for created chunks
871
875
  */
872
876
  automaticNameDelimiter?: string;
877
+ /**
878
+ * Sets the max length for the name of a created chunk
879
+ */
880
+ automaticNameMaxLength?: number;
873
881
  /**
874
882
  * Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)
875
883
  */
@@ -887,6 +895,10 @@ export interface OptimizationSplitChunksOptions {
887
895
  * Sets the name delimiter for created chunks
888
896
  */
889
897
  automaticNameDelimiter?: string;
898
+ /**
899
+ * Sets the max length for the name of a created chunk
900
+ */
901
+ automaticNameMaxLength?: number;
890
902
  /**
891
903
  * Sets the name prefix for created chunks
892
904
  */
@@ -28,6 +28,7 @@ class JsonGenerator {
28
28
  })
29
29
  );
30
30
  }
31
+ let finalJson;
31
32
  if (
32
33
  Array.isArray(module.buildMeta.providedExports) &&
33
34
  !module.isUsed("default")
@@ -41,12 +42,14 @@ class JsonGenerator {
41
42
  reducedJson[used] = data[exportName];
42
43
  }
43
44
  }
44
- source.add(
45
- `${module.moduleArgument}.exports = ${stringifySafe(reducedJson)};`
46
- );
45
+ finalJson = reducedJson;
47
46
  } else {
48
- source.add(`${module.moduleArgument}.exports = ${stringifySafe(data)};`);
47
+ finalJson = data;
49
48
  }
49
+ // Use JSON because JSON.parse() is much faster than JavaScript evaluation
50
+ const jsonSource = JSON.stringify(stringifySafe(finalJson));
51
+ const jsonExpr = `JSON.parse(${jsonSource})`;
52
+ source.add(`${module.moduleArgument}.exports = ${jsonExpr};`);
50
53
  return source;
51
54
  }
52
55
  }
@@ -18,6 +18,18 @@ class MultiWatching {
18
18
  }
19
19
  }
20
20
 
21
+ suspend() {
22
+ for (const watching of this.watchings) {
23
+ watching.suspend();
24
+ }
25
+ }
26
+
27
+ resume() {
28
+ for (const watching of this.watchings) {
29
+ watching.resume();
30
+ }
31
+ }
32
+
21
33
  close(callback) {
22
34
  asyncLib.forEach(
23
35
  this.watchings,
@@ -335,7 +335,11 @@ class NormalModuleFactory extends Tapable {
335
335
  ],
336
336
  (err, results) => {
337
337
  if (err) return callback(err);
338
- loaders = results[0].concat(loaders, results[1], results[2]);
338
+ if (matchResource === undefined) {
339
+ loaders = results[0].concat(loaders, results[1], results[2]);
340
+ } else {
341
+ loaders = results[0].concat(results[1], loaders, results[2]);
342
+ }
339
343
  process.nextTick(() => {
340
344
  const type = settings.type;
341
345
  const resolveOptions = settings.resolve;
@@ -4,8 +4,14 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
- const getProperty = (obj, name) => {
8
- name = name.split(".");
7
+ /**
8
+ * Gets the value at path of object
9
+ * @param {object} obj - object to query
10
+ * @param {string} path - query path
11
+ * @returns {any} - if {@param path} requests element from array, then `undefined` will be returned
12
+ */
13
+ const getProperty = (obj, path) => {
14
+ let name = path.split(".");
9
15
  for (let i = 0; i < name.length - 1; i++) {
10
16
  obj = obj[name[i]];
11
17
  if (typeof obj !== "object" || !obj || Array.isArray(obj)) return;
@@ -13,8 +19,15 @@ const getProperty = (obj, name) => {
13
19
  return obj[name.pop()];
14
20
  };
15
21
 
16
- const setProperty = (obj, name, value) => {
17
- name = name.split(".");
22
+ /**
23
+ * Sets the value at path of object. Stops execution, if {@param path} requests element from array to be set
24
+ * @param {object} obj - object to query
25
+ * @param {string} path - query path
26
+ * @param {any} value - value to be set
27
+ * @returns {void}
28
+ */
29
+ const setProperty = (obj, path, value) => {
30
+ let name = path.split(".");
18
31
  for (let i = 0; i < name.length - 1; i++) {
19
32
  if (typeof obj[name[i]] !== "object" && obj[name[i]] !== undefined) return;
20
33
  if (Array.isArray(obj[name[i]])) return;
@@ -24,21 +37,53 @@ const setProperty = (obj, name, value) => {
24
37
  obj[name.pop()] = value;
25
38
  };
26
39
 
40
+ /**
41
+ * @typedef {'call' | 'make' | 'append'} ConfigType
42
+ */
43
+ /**
44
+ * @typedef {(options: object) => any} MakeConfigHandler
45
+ */
46
+ /**
47
+ * @typedef {(value: any, options: object) => any} CallConfigHandler
48
+ */
49
+ /**
50
+ * @typedef {any[]} AppendConfigValues
51
+ */
52
+
27
53
  class OptionsDefaulter {
28
54
  constructor() {
55
+ /**
56
+ * Stores default options settings or functions for computing them
57
+ */
29
58
  this.defaults = {};
59
+ /**
60
+ * Stores configuration for options
61
+ * @type {{[key: string]: ConfigType}}
62
+ */
30
63
  this.config = {};
31
64
  }
32
65
 
66
+ /**
67
+ * Enhancing {@param options} with default values
68
+ * @param {object} options - provided options
69
+ * @returns {object} - enhanced options
70
+ * @throws {Error} - will throw error, if configuration value is other then `undefined` or {@link ConfigType}
71
+ */
33
72
  process(options) {
34
73
  options = Object.assign({}, options);
35
74
  for (let name in this.defaults) {
36
75
  switch (this.config[name]) {
76
+ /**
77
+ * If {@link ConfigType} doesn't specified and current value is `undefined`, then default value will be assigned
78
+ */
37
79
  case undefined:
38
80
  if (getProperty(options, name) === undefined) {
39
81
  setProperty(options, name, this.defaults[name]);
40
82
  }
41
83
  break;
84
+ /**
85
+ * Assign result of {@link CallConfigHandler}
86
+ */
42
87
  case "call":
43
88
  setProperty(
44
89
  options,
@@ -46,11 +91,17 @@ class OptionsDefaulter {
46
91
  this.defaults[name].call(this, getProperty(options, name), options)
47
92
  );
48
93
  break;
94
+ /**
95
+ * Assign result of {@link MakeConfigHandler}, if current value is `undefined`
96
+ */
49
97
  case "make":
50
98
  if (getProperty(options, name) === undefined) {
51
99
  setProperty(options, name, this.defaults[name].call(this, options));
52
100
  }
53
101
  break;
102
+ /**
103
+ * Adding {@link AppendConfigValues} at the end of the current array
104
+ */
54
105
  case "append": {
55
106
  let oldValue = getProperty(options, name);
56
107
  if (!Array.isArray(oldValue)) {
@@ -69,6 +120,13 @@ class OptionsDefaulter {
69
120
  return options;
70
121
  }
71
122
 
123
+ /**
124
+ * Builds up default values
125
+ * @param {string} name - option path
126
+ * @param {ConfigType | any} config - if {@param def} is provided, then only {@link ConfigType} is allowed
127
+ * @param {MakeConfigHandler | CallConfigHandler | AppendConfigValues} [def] - defaults
128
+ * @returns {void}
129
+ */
72
130
  set(name, config, def) {
73
131
  if (def !== undefined) {
74
132
  this.defaults[name] = def;
package/lib/Parser.js CHANGED
@@ -7,14 +7,13 @@
7
7
  // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
8
8
 
9
9
  const acorn = require("acorn");
10
- const acornDynamicImport = require("acorn-dynamic-import").default;
11
10
  const { Tapable, SyncBailHook, HookMap } = require("tapable");
12
11
  const util = require("util");
13
12
  const vm = require("vm");
14
13
  const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
15
14
  const StackedSetMap = require("./util/StackedSetMap");
16
15
 
17
- const acornParser = acorn.Parser.extend(acornDynamicImport);
16
+ const acornParser = acorn.Parser;
18
17
 
19
18
  const joinRanges = (startRange, endRange) => {
20
19
  if (!endRange) return startRange;
@@ -25,7 +24,7 @@ const joinRanges = (startRange, endRange) => {
25
24
  const defaultParserOptions = {
26
25
  ranges: true,
27
26
  locations: true,
28
- ecmaVersion: 2019,
27
+ ecmaVersion: 11,
29
28
  sourceType: "module",
30
29
  onComment: null
31
30
  };
@@ -18,7 +18,8 @@ const createDefaultHandler = profile => {
18
18
 
19
19
  const defaultHandler = (percentage, msg, ...args) => {
20
20
  let state = msg;
21
- const details = args;
21
+ const details = args.filter(v => v.length);
22
+ const maxLineLength = process.stderr.columns || Infinity;
22
23
  if (percentage < 1) {
23
24
  percentage = Math.floor(percentage * 100);
24
25
  msg = `${percentage}% ${msg}`;
@@ -28,12 +29,28 @@ const createDefaultHandler = profile => {
28
29
  if (percentage < 10) {
29
30
  msg = ` ${msg}`;
30
31
  }
31
- for (let detail of details) {
32
- if (!detail) continue;
33
- if (detail.length > 40) {
34
- detail = `...${detail.substr(detail.length - 39)}`;
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}`;
35
53
  }
36
- msg += ` ${detail}`;
37
54
  }
38
55
  }
39
56
  if (profile) {
@@ -55,6 +72,7 @@ const createDefaultHandler = profile => {
55
72
  }
56
73
  if (lastMessage !== msg) {
57
74
  goToLineStart(msg);
75
+ msg = msg.substring(0, maxLineLength);
58
76
  process.stderr.write(msg);
59
77
  lastMessage = msg;
60
78
  }
package/lib/Watching.js CHANGED
@@ -13,6 +13,7 @@ class Watching {
13
13
  this.handler = handler;
14
14
  this.callbacks = [];
15
15
  this.closed = false;
16
+ this.suspended = false;
16
17
  if (typeof watchOptions === "number") {
17
18
  this.watchOptions = {
18
19
  aggregateTimeout: watchOptions
@@ -133,7 +134,9 @@ class Watching {
133
134
  this.compiler.fileTimestamps = fileTimestamps;
134
135
  this.compiler.contextTimestamps = contextTimestamps;
135
136
  this.compiler.removedFiles = removedFiles;
136
- this._invalidate();
137
+ if (!this.suspended) {
138
+ this._invalidate();
139
+ }
137
140
  },
138
141
  (fileName, changeTime) => {
139
142
  this.compiler.hooks.invalid.call(fileName, changeTime);
@@ -158,6 +161,7 @@ class Watching {
158
161
  this.watcher.pause();
159
162
  this.watcher = null;
160
163
  }
164
+
161
165
  if (this.running) {
162
166
  this.invalid = true;
163
167
  return false;
@@ -166,6 +170,18 @@ class Watching {
166
170
  }
167
171
  }
168
172
 
173
+ suspend() {
174
+ this.suspended = true;
175
+ this.invalid = false;
176
+ }
177
+
178
+ resume() {
179
+ if (this.suspended) {
180
+ this.suspended = false;
181
+ this._invalidate();
182
+ }
183
+ }
184
+
169
185
  close(callback) {
170
186
  const finalCallback = () => {
171
187
  this.compiler.hooks.watchClose.call();
@@ -231,6 +231,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
231
231
  return isProductionLikeMode(options) ? 5 : Infinity;
232
232
  });
233
233
  this.set("optimization.splitChunks.automaticNameDelimiter", "~");
234
+ this.set("optimization.splitChunks.automaticNameMaxLength", 109);
234
235
  this.set("optimization.splitChunks.maxInitialRequests", "make", options => {
235
236
  return isProductionLikeMode(options) ? 3 : Infinity;
236
237
  });
@@ -123,9 +123,11 @@ module.exports = class SplitChunksPlugin {
123
123
  getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({
124
124
  cacheGroups: options.cacheGroups,
125
125
  name: options.name,
126
- automaticNameDelimiter: options.automaticNameDelimiter
126
+ automaticNameDelimiter: options.automaticNameDelimiter,
127
+ automaticNameMaxLength: options.automaticNameMaxLength
127
128
  }),
128
129
  automaticNameDelimiter: options.automaticNameDelimiter,
130
+ automaticNameMaxLength: options.automaticNameMaxLength || 109,
129
131
  fallbackCacheGroup: SplitChunksPlugin.normalizeFallbackCacheGroup(
130
132
  options.fallbackCacheGroup || {},
131
133
  options
@@ -133,7 +135,12 @@ module.exports = class SplitChunksPlugin {
133
135
  };
134
136
  }
135
137
 
136
- static normalizeName({ name, automaticNameDelimiter, automaticNamePrefix }) {
138
+ static normalizeName({
139
+ name,
140
+ automaticNameDelimiter,
141
+ automaticNamePrefix,
142
+ automaticNameMaxLength
143
+ }) {
137
144
  if (name === true) {
138
145
  /** @type {WeakMap<Chunk[], Record<string, string>>} */
139
146
  const cache = new WeakMap();
@@ -160,11 +167,17 @@ module.exports = class SplitChunksPlugin {
160
167
  // Filenames and paths can't be too long otherwise an
161
168
  // ENAMETOOLONG error is raised. If the generated name if too
162
169
  // long, it is truncated and a hash is appended. The limit has
163
- // been set to 100 to prevent `[name].[chunkhash].[ext]` from
170
+ // been set to 109 to prevent `[name].[chunkhash].[ext]` from
164
171
  // generating a 256+ character string.
165
- if (name.length > 100) {
172
+ if (name.length > automaticNameMaxLength) {
173
+ const hashedFilename = hashFilename(name);
174
+ const sliceLength =
175
+ automaticNameMaxLength -
176
+ (automaticNameDelimiter.length + hashedFilename.length);
166
177
  name =
167
- name.slice(0, 100) + automaticNameDelimiter + hashFilename(name);
178
+ name.slice(0, sliceLength) +
179
+ automaticNameDelimiter +
180
+ hashFilename(name);
168
181
  }
169
182
  cacheEntry[cacheGroup] = name;
170
183
  return name;
@@ -213,7 +226,12 @@ module.exports = class SplitChunksPlugin {
213
226
  };
214
227
  }
215
228
 
216
- static normalizeCacheGroups({ cacheGroups, name, automaticNameDelimiter }) {
229
+ static normalizeCacheGroups({
230
+ cacheGroups,
231
+ name,
232
+ automaticNameDelimiter,
233
+ automaticNameMaxLength
234
+ }) {
217
235
  if (typeof cacheGroups === "function") {
218
236
  // TODO webpack 5 remove this
219
237
  if (cacheGroups.length !== 1) {
@@ -259,7 +277,9 @@ module.exports = class SplitChunksPlugin {
259
277
  typeof option.automaticNameDelimiter === "string"
260
278
  ? option.automaticNameDelimiter
261
279
  : automaticNameDelimiter,
262
- automaticNamePrefix: option.automaticNamePrefix
280
+ automaticNamePrefix: option.automaticNamePrefix,
281
+ automaticNameMaxLength:
282
+ option.automaticNameMaxLength || automaticNameMaxLength
263
283
  }) || (() => {}),
264
284
  chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
265
285
  option.chunks
package/lib/webpack.js CHANGED
@@ -32,7 +32,9 @@ const webpack = (options, callback) => {
32
32
  }
33
33
  let compiler;
34
34
  if (Array.isArray(options)) {
35
- compiler = new MultiCompiler(options.map(options => webpack(options)));
35
+ compiler = new MultiCompiler(
36
+ Array.from(options).map(options => webpack(options))
37
+ );
36
38
  } else if (typeof options === "object") {
37
39
  options = new WebpackOptionsDefaulter().process(options);
38
40
 
@@ -45,6 +45,7 @@ class WebWorkerMainTemplatePlugin {
45
45
  "if(!installedChunks[chunkId]) {",
46
46
  Template.indent([
47
47
  "importScripts(" +
48
+ "__webpack_require__.p + " +
48
49
  mainTemplate.getAssetPath(JSON.stringify(chunkFilename), {
49
50
  hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
50
51
  hashWithLength: length =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack",
3
- "version": "4.34.0",
3
+ "version": "4.35.3",
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",
@@ -9,8 +9,7 @@
9
9
  "@webassemblyjs/helper-module-context": "1.8.5",
10
10
  "@webassemblyjs/wasm-edit": "1.8.5",
11
11
  "@webassemblyjs/wasm-parser": "1.8.5",
12
- "acorn": "^6.0.5",
13
- "acorn-dynamic-import": "^4.0.0",
12
+ "acorn": "^6.2.0",
14
13
  "ajv": "^6.1.0",
15
14
  "ajv-keywords": "^3.1.0",
16
15
  "chrome-trace-event": "^1.0.0",
@@ -72,6 +71,7 @@
72
71
  "rimraf": "^2.6.2",
73
72
  "script-loader": "~0.7.0",
74
73
  "simple-git": "^1.65.0",
74
+ "strip-ansi": "^5.2.0",
75
75
  "style-loader": "^0.23.1",
76
76
  "typescript": "^3.0.0-rc",
77
77
  "url-loader": "^1.1.2",
@@ -553,6 +553,11 @@
553
553
  "type": "string",
554
554
  "minLength": 1
555
555
  },
556
+ "automaticNameMaxLength": {
557
+ "description": "Sets the max length for the name of a created chunk",
558
+ "type": "number",
559
+ "minimum": 1
560
+ },
556
561
  "cacheGroups": {
557
562
  "description": "Assign modules to a cache group (modules from different cache groups are tried to keep in separate chunks)",
558
563
  "type": "object",
@@ -582,6 +587,11 @@
582
587
  "type": "string",
583
588
  "minLength": 1
584
589
  },
590
+ "automaticNameMaxLength": {
591
+ "description": "Sets the max length for the name of a created chunk",
592
+ "type": "number",
593
+ "minimum": 1
594
+ },
585
595
  "automaticNamePrefix": {
586
596
  "description": "Sets the name prefix for created chunks",
587
597
  "type": "string"
@@ -1511,6 +1521,14 @@
1511
1521
  }
1512
1522
  ]
1513
1523
  },
1524
+ "realResource": {
1525
+ "description": "Match rules with custom resource name",
1526
+ "anyOf": [
1527
+ {
1528
+ "$ref": "#/definitions/RuleSetConditionOrConditionsAbsolute"
1529
+ }
1530
+ ]
1531
+ },
1514
1532
  "resolve": {
1515
1533
  "description": "Options for the resolver",
1516
1534
  "type": "object",