webpack 4.10.1 → 4.12.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.
Files changed (118) hide show
  1. package/lib/AmdMainTemplatePlugin.js +3 -1
  2. package/lib/AsyncDependencyToInitialChunkError.js +4 -4
  3. package/lib/BannerPlugin.js +3 -1
  4. package/lib/BasicEvaluatedExpression.js +14 -11
  5. package/lib/CachePlugin.js +12 -5
  6. package/lib/CaseSensitiveModulesWarning.js +41 -45
  7. package/lib/Chunk.js +56 -19
  8. package/lib/ChunkGroup.js +14 -6
  9. package/lib/CommentCompilationWarning.js +22 -0
  10. package/lib/Compilation.js +72 -29
  11. package/lib/Compiler.js +22 -10
  12. package/lib/ConstPlugin.js +25 -9
  13. package/lib/ContextModule.js +88 -36
  14. package/lib/ContextModuleFactory.js +18 -7
  15. package/lib/ContextReplacementPlugin.js +14 -7
  16. package/lib/DefinePlugin.js +15 -6
  17. package/lib/DependenciesBlock.js +3 -1
  18. package/lib/DependenciesBlockVariable.js +2 -1
  19. package/lib/DllPlugin.js +4 -2
  20. package/lib/DynamicEntryPlugin.js +4 -2
  21. package/lib/EntryModuleNotFoundError.js +21 -22
  22. package/lib/ErrorHelpers.js +5 -2
  23. package/lib/EvalSourceMapDevToolPlugin.js +2 -1
  24. package/lib/FlagDependencyUsagePlugin.js +11 -5
  25. package/lib/FunctionModuleTemplatePlugin.js +8 -6
  26. package/lib/HarmonyLinkingError.js +1 -2
  27. package/lib/HotModuleReplacement.runtime.js +13 -4
  28. package/lib/HotModuleReplacementPlugin.js +13 -6
  29. package/lib/JavascriptGenerator.js +2 -1
  30. package/lib/JavascriptModulesPlugin.js +4 -9
  31. package/lib/JsonParser.js +2 -1
  32. package/lib/LibraryTemplatePlugin.js +2 -1
  33. package/lib/LoaderOptionsPlugin.js +2 -1
  34. package/lib/MainTemplate.js +2 -1
  35. package/lib/Module.js +13 -5
  36. package/lib/ModuleBuildError.js +22 -12
  37. package/lib/ModuleDependencyError.js +4 -4
  38. package/lib/ModuleDependencyWarning.js +4 -4
  39. package/lib/ModuleError.js +13 -5
  40. package/lib/ModuleFilenameHelpers.js +20 -8
  41. package/lib/ModuleNotFoundError.js +23 -26
  42. package/lib/ModuleParseError.js +27 -14
  43. package/lib/ModuleWarning.js +13 -7
  44. package/lib/MultiCompiler.js +19 -7
  45. package/lib/MultiModule.js +5 -2
  46. package/lib/NodeStuffPlugin.js +2 -1
  47. package/lib/NormalModule.js +80 -16
  48. package/lib/NormalModuleFactory.js +67 -24
  49. package/lib/OptionsDefaulter.js +7 -3
  50. package/lib/Parser.js +182 -75
  51. package/lib/ParserHelpers.js +6 -3
  52. package/lib/ProgressPlugin.js +17 -2
  53. package/lib/RawModule.js +4 -2
  54. package/lib/RecordIdsPlugin.js +77 -9
  55. package/lib/RemovedPluginError.js +1 -3
  56. package/lib/RequestShortener.js +15 -6
  57. package/lib/RuleSet.js +51 -18
  58. package/lib/RuntimeTemplate.js +21 -10
  59. package/lib/SourceMapDevToolPlugin.js +4 -3
  60. package/lib/Stats.js +74 -31
  61. package/lib/Template.js +7 -4
  62. package/lib/TemplatedPathPlugin.js +6 -3
  63. package/lib/UmdMainTemplatePlugin.js +8 -3
  64. package/lib/UnsupportedFeatureWarning.js +22 -21
  65. package/lib/WarnCaseSensitiveModulesPlugin.js +2 -1
  66. package/lib/Watching.js +3 -2
  67. package/lib/WebpackOptionsApply.js +51 -23
  68. package/lib/WebpackOptionsDefaulter.js +15 -9
  69. package/lib/WebpackOptionsValidationError.js +63 -34
  70. package/lib/debug/ProfilingPlugin.js +11 -2
  71. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +17 -8
  72. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +8 -4
  73. package/lib/dependencies/HarmonyDetectionParserPlugin.js +4 -2
  74. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +7 -3
  75. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +6 -3
  76. package/lib/dependencies/ImportParserPlugin.js +42 -11
  77. package/lib/dependencies/LoaderPlugin.js +12 -7
  78. package/lib/dependencies/LocalModulesHelpers.js +13 -6
  79. package/lib/dependencies/RequireContextPlugin.js +4 -2
  80. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +8 -4
  81. package/lib/dependencies/SystemPlugin.js +6 -6
  82. package/lib/dependencies/WebAssemblyExportImportedDependency.js +29 -0
  83. package/lib/dependencies/WebAssemblyImportDependency.js +1 -1
  84. package/lib/formatLocation.js +15 -7
  85. package/lib/node/NodeMainTemplateAsync.runtime.js +1 -1
  86. package/lib/node/NodeMainTemplatePlugin.js +6 -3
  87. package/lib/node/NodeSourcePlugin.js +9 -5
  88. package/lib/node/NodeWatchFileSystem.js +29 -12
  89. package/lib/node/ReadFileCompileWasmTemplatePlugin.js +11 -2
  90. package/lib/optimize/AggressiveSplittingPlugin.js +12 -6
  91. package/lib/optimize/ConcatenatedModule.js +19 -8
  92. package/lib/optimize/MergeDuplicateChunksPlugin.js +6 -3
  93. package/lib/optimize/ModuleConcatenationPlugin.js +23 -10
  94. package/lib/optimize/OccurrenceOrderPlugin.js +11 -4
  95. package/lib/optimize/RemoveParentModulesPlugin.js +17 -7
  96. package/lib/optimize/SideEffectsFlagPlugin.js +14 -3
  97. package/lib/optimize/SplitChunksPlugin.js +33 -20
  98. package/lib/performance/AssetsOverSizeLimitWarning.js +7 -7
  99. package/lib/performance/EntrypointsOverSizeLimitWarning.js +6 -7
  100. package/lib/performance/NoAsyncChunksWarning.js +5 -5
  101. package/lib/util/SortableSet.js +5 -2
  102. package/lib/util/StackedSetMap.js +12 -5
  103. package/lib/wasm/UnsupportedWebAssemblyFeatureError.js +1 -2
  104. package/lib/wasm/WasmFinalizeExportsPlugin.js +66 -0
  105. package/lib/wasm/WasmMainTemplatePlugin.js +87 -43
  106. package/lib/wasm/WebAssemblyGenerator.js +117 -74
  107. package/lib/wasm/WebAssemblyJavascriptGenerator.js +92 -49
  108. package/lib/wasm/WebAssemblyModulesPlugin.js +11 -1
  109. package/lib/wasm/WebAssemblyParser.js +96 -24
  110. package/lib/wasm/WebAssemblyUtils.js +17 -6
  111. package/lib/web/FetchCompileWasmTemplatePlugin.js +13 -1
  112. package/lib/web/JsonpChunkTemplatePlugin.js +7 -0
  113. package/lib/web/JsonpMainTemplate.runtime.js +2 -1
  114. package/lib/web/JsonpMainTemplatePlugin.js +68 -63
  115. package/lib/webpack.js +2 -1
  116. package/lib/webworker/WebWorkerMainTemplate.runtime.js +2 -1
  117. package/package.json +12 -11
  118. package/schemas/WebpackOptions.json +8 -0
@@ -48,8 +48,9 @@ const getHash = str => {
48
48
  };
49
49
 
50
50
  const asRegExp = test => {
51
- if (typeof test === "string")
51
+ if (typeof test === "string") {
52
52
  test = new RegExp("^" + test.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"));
53
+ }
53
54
  return test;
54
55
  };
55
56
 
@@ -141,7 +142,9 @@ ModuleFilenameHelpers.replaceDuplicates = (array, fn, comparator) => {
141
142
  if (countMap[item].length > 1) {
142
143
  if (comparator && countMap[item][0] === i) return item;
143
144
  return fn(item, i, posMap[item]++);
144
- } else return item;
145
+ } else {
146
+ return item;
147
+ }
145
148
  });
146
149
  };
147
150
 
@@ -156,11 +159,20 @@ ModuleFilenameHelpers.matchPart = (str, test) => {
156
159
  };
157
160
 
158
161
  ModuleFilenameHelpers.matchObject = (obj, str) => {
159
- if (obj.test)
160
- if (!ModuleFilenameHelpers.matchPart(str, obj.test)) return false;
161
- if (obj.include)
162
- if (!ModuleFilenameHelpers.matchPart(str, obj.include)) return false;
163
- if (obj.exclude)
164
- if (ModuleFilenameHelpers.matchPart(str, obj.exclude)) return false;
162
+ if (obj.test) {
163
+ if (!ModuleFilenameHelpers.matchPart(str, obj.test)) {
164
+ return false;
165
+ }
166
+ }
167
+ if (obj.include) {
168
+ if (!ModuleFilenameHelpers.matchPart(str, obj.include)) {
169
+ return false;
170
+ }
171
+ }
172
+ if (obj.exclude) {
173
+ if (ModuleFilenameHelpers.matchPart(str, obj.exclude)) {
174
+ return false;
175
+ }
176
+ }
165
177
  return true;
166
178
  };
@@ -1,26 +1,23 @@
1
- /*
2
- MIT License http://www.opensource.org/licenses/mit-license.php
3
- Author Tobias Koppers @sokra
4
- */
5
- "use strict";
6
-
7
- const WebpackError = require("./WebpackError");
8
-
9
- class ModuleNotFoundError extends WebpackError {
10
- constructor(module, err, dependencies) {
11
- super();
12
-
13
- this.name = "ModuleNotFoundError";
14
- this.message = "Module not found: " + err;
15
- this.details = err.details;
16
- this.missing = err.missing;
17
- this.module = module;
18
- this.origin = module;
19
- this.dependencies = dependencies;
20
- this.error = err;
21
-
22
- Error.captureStackTrace(this, this.constructor);
23
- }
24
- }
25
-
26
- module.exports = ModuleNotFoundError;
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+
7
+ const WebpackError = require("./WebpackError");
8
+
9
+ class ModuleNotFoundError extends WebpackError {
10
+ constructor(module, err) {
11
+ super("Module not found: " + err);
12
+
13
+ this.name = "ModuleNotFoundError";
14
+ this.details = err.details;
15
+ this.missing = err.missing;
16
+ this.module = module;
17
+ this.error = err;
18
+
19
+ Error.captureStackTrace(this, this.constructor);
20
+ }
21
+ }
22
+
23
+ module.exports = ModuleNotFoundError;
@@ -6,14 +6,18 @@
6
6
 
7
7
  const WebpackError = require("./WebpackError");
8
8
 
9
+ /** @typedef {import("./Module")} Module */
10
+
9
11
  class ModuleParseError extends WebpackError {
12
+ /**
13
+ * @param {Module} module the errored module
14
+ * @param {string} source source code
15
+ * @param {Error&any} err the parse error
16
+ */
10
17
  constructor(module, source, err) {
11
- super();
12
-
13
- this.name = "ModuleParseError";
14
- this.message = "Module parse failed: " + err.message;
15
- this.message +=
16
- "\nYou may need an appropriate loader to handle this file type.";
18
+ let message = "Module parse failed: " + err.message;
19
+ let loc = undefined;
20
+ message += "\nYou may need an appropriate loader to handle this file type.";
17
21
  if (
18
22
  err.loc &&
19
23
  typeof err.loc === "object" &&
@@ -22,19 +26,28 @@ class ModuleParseError extends WebpackError {
22
26
  var lineNumber = err.loc.line;
23
27
  if (/[\0\u0001\u0002\u0003\u0004\u0005\u0006\u0007]/.test(source)) {
24
28
  // binary file
25
- this.message += "\n(Source code omitted for this binary file)";
29
+ message += "\n(Source code omitted for this binary file)";
26
30
  } else {
27
- source = source.split("\n");
28
- this.message +=
29
- "\n| " +
30
- source
31
- .slice(Math.max(0, lineNumber - 3), lineNumber + 2)
32
- .join("\n| ");
31
+ const sourceLines = source.split("\n");
32
+ const start = Math.max(0, lineNumber - 3);
33
+ const linesBefore = sourceLines.slice(start, lineNumber - 1);
34
+ const theLine = sourceLines[lineNumber - 1];
35
+ const linesAfter = sourceLines.slice(lineNumber, lineNumber + 2);
36
+ message +=
37
+ linesBefore.map(l => `\n| ${l}`).join("") +
38
+ `\n> ${theLine}` +
39
+ linesAfter.map(l => `\n| ${l}`).join("");
33
40
  }
41
+ loc = err.loc;
34
42
  } else {
35
- this.message += "\n" + err.stack;
43
+ message += "\n" + err.stack;
36
44
  }
45
+
46
+ super(message);
47
+
48
+ this.name = "ModuleParseError";
37
49
  this.module = module;
50
+ this.loc = loc;
38
51
  this.error = err;
39
52
 
40
53
  Error.captureStackTrace(this, this.constructor);
@@ -8,15 +8,21 @@ const WebpackError = require("./WebpackError");
8
8
  const { cleanUp } = require("./ErrorHelpers");
9
9
 
10
10
  class ModuleWarning extends WebpackError {
11
- constructor(module, warning) {
12
- super();
13
-
11
+ constructor(module, warning, { from = null } = {}) {
12
+ let message = "Module Warning";
13
+ if (from) {
14
+ message += ` (from ${from}):\n`;
15
+ } else {
16
+ message += ": ";
17
+ }
18
+ if (warning && typeof warning === "object" && warning.message) {
19
+ message += warning.message;
20
+ } else if (warning) {
21
+ message += warning;
22
+ }
23
+ super(message);
14
24
  this.name = "ModuleWarning";
15
25
  this.module = module;
16
- this.message =
17
- warning && typeof warning === "object" && warning.message
18
- ? warning.message
19
- : warning;
20
26
  this.warning = warning;
21
27
  this.details =
22
28
  warning && typeof warning === "object" && warning.stack
@@ -162,8 +162,11 @@ module.exports = class MultiCompiler extends Tapable {
162
162
  for (const c of list) {
163
163
  const ready =
164
164
  !c.dependencies || c.dependencies.every(isDependencyFulfilled);
165
- if (ready) readyCompilers.push(c);
166
- else remainingCompilers.push(c);
165
+ if (ready) {
166
+ readyCompilers.push(c);
167
+ } else {
168
+ remainingCompilers.push(c);
169
+ }
167
170
  }
168
171
  return readyCompilers;
169
172
  };
@@ -233,12 +236,16 @@ module.exports = class MultiCompiler extends Tapable {
233
236
  }
234
237
 
235
238
  run(callback) {
236
- if (this.running) return callback(new ConcurrentCompilationError());
239
+ if (this.running) {
240
+ return callback(new ConcurrentCompilationError());
241
+ }
237
242
 
238
243
  const finalCallback = (err, stats) => {
239
244
  this.running = false;
240
245
 
241
- if (callback !== undefined) return callback(err, stats);
246
+ if (callback !== undefined) {
247
+ return callback(err, stats);
248
+ }
242
249
  };
243
250
 
244
251
  const allStats = this.compilers.map(() => null);
@@ -249,13 +256,17 @@ module.exports = class MultiCompiler extends Tapable {
249
256
  (compiler, callback) => {
250
257
  const compilerIdx = this.compilers.indexOf(compiler);
251
258
  compiler.run((err, stats) => {
252
- if (err) return callback(err);
259
+ if (err) {
260
+ return callback(err);
261
+ }
253
262
  allStats[compilerIdx] = stats;
254
263
  callback();
255
264
  });
256
265
  },
257
266
  err => {
258
- if (err) return finalCallback(err);
267
+ if (err) {
268
+ return finalCallback(err);
269
+ }
259
270
  finalCallback(null, new MultiStats(allStats));
260
271
  }
261
272
  );
@@ -264,8 +275,9 @@ module.exports = class MultiCompiler extends Tapable {
264
275
 
265
276
  purgeInputFileSystem() {
266
277
  for (const compiler of this.compilers) {
267
- if (compiler.inputFileSystem && compiler.inputFileSystem.purge)
278
+ if (compiler.inputFileSystem && compiler.inputFileSystem.purge) {
268
279
  compiler.inputFileSystem.purge();
280
+ }
269
281
  }
270
282
  }
271
283
  };
@@ -56,10 +56,13 @@ class MultiModule extends Module {
56
56
  let idx = 0;
57
57
  for (const dep of this.dependencies) {
58
58
  if (dep.module) {
59
- if (idx === this.dependencies.length - 1) str.push("module.exports = ");
59
+ if (idx === this.dependencies.length - 1) {
60
+ str.push("module.exports = ");
61
+ }
60
62
  str.push("__webpack_require__(");
61
- if (runtimeTemplate.outputOptions.pathinfo)
63
+ if (runtimeTemplate.outputOptions.pathinfo) {
62
64
  str.push(Template.toComment(dep.request));
65
+ }
63
66
  str.push(`${JSON.stringify(dep.module.id)}`);
64
67
  str.push(")");
65
68
  } else {
@@ -30,8 +30,9 @@ class NodeStuffPlugin {
30
30
  if (parserOptions.node === false) return;
31
31
 
32
32
  let localOptions = options;
33
- if (parserOptions.node)
33
+ if (parserOptions.node) {
34
34
  localOptions = Object.assign({}, localOptions, parserOptions.node);
35
+ }
35
36
 
36
37
  const setConstant = (expressionName, value) => {
37
38
  parser.hooks.expression
@@ -43,9 +43,18 @@ const contextify = (context, request) => {
43
43
  .split("!")
44
44
  .map(r => {
45
45
  const splitPath = r.split("?");
46
- splitPath[0] = path.relative(context, splitPath[0]);
47
- if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
48
- if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
46
+ if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
47
+ splitPath[0] = path.win32.relative(context, splitPath[0]);
48
+ if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
49
+ splitPath[0] = splitPath[0].replace(/\\/g, "/");
50
+ }
51
+ }
52
+ if (/^\//.test(splitPath[0])) {
53
+ splitPath[0] = path.posix.relative(context, splitPath[0]);
54
+ }
55
+ if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
56
+ splitPath[0] = "./" + splitPath[0];
57
+ }
49
58
  return splitPath.join("?");
50
59
  })
51
60
  .join("!");
@@ -76,6 +85,7 @@ class NormalModule extends Module {
76
85
  rawRequest,
77
86
  loaders,
78
87
  resource,
88
+ matchResource,
79
89
  parser,
80
90
  generator,
81
91
  resolveOptions
@@ -90,6 +100,7 @@ class NormalModule extends Module {
90
100
  this.parser = parser;
91
101
  this.generator = generator;
92
102
  this.resource = resource;
103
+ this.matchResource = matchResource;
93
104
  this.loaders = loaders;
94
105
  if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
95
106
 
@@ -123,16 +134,21 @@ class NormalModule extends Module {
123
134
  }
124
135
 
125
136
  nameForCondition() {
126
- const idx = this.resource.indexOf("?");
127
- if (idx >= 0) return this.resource.substr(0, idx);
128
- return this.resource;
137
+ const resource = this.matchResource || this.resource;
138
+ const idx = resource.indexOf("?");
139
+ if (idx >= 0) return resource.substr(0, idx);
140
+ return resource;
129
141
  }
130
142
 
131
143
  updateCacheModule(module) {
144
+ this.type = module.type;
145
+ this.request = module.request;
132
146
  this.userRequest = module.userRequest;
147
+ this.rawRequest = module.rawRequest;
133
148
  this.parser = module.parser;
134
149
  this.generator = module.generator;
135
150
  this.resource = module.resource;
151
+ this.matchResource = module.matchResource;
136
152
  this.loaders = module.loaders;
137
153
  this.resolveOptions = module.resolveOptions;
138
154
  }
@@ -150,16 +166,30 @@ class NormalModule extends Module {
150
166
  }
151
167
 
152
168
  createLoaderContext(resolver, options, compilation, fs) {
169
+ const requestShortener = compilation.runtimeTemplate.requestShortener;
153
170
  const loaderContext = {
154
171
  version: 2,
155
172
  emitWarning: warning => {
156
- if (!(warning instanceof Error))
173
+ if (!(warning instanceof Error)) {
157
174
  warning = new NonErrorEmittedError(warning);
158
- this.warnings.push(new ModuleWarning(this, warning));
175
+ }
176
+ const currentLoader = this.getCurrentLoader(loaderContext);
177
+ this.warnings.push(
178
+ new ModuleWarning(this, warning, {
179
+ from: requestShortener.shorten(currentLoader.loader)
180
+ })
181
+ );
159
182
  },
160
183
  emitError: error => {
161
- if (!(error instanceof Error)) error = new NonErrorEmittedError(error);
162
- this.errors.push(new ModuleError(this, error));
184
+ if (!(error instanceof Error)) {
185
+ error = new NonErrorEmittedError(error);
186
+ }
187
+ const currentLoader = this.getCurrentLoader(loaderContext);
188
+ this.errors.push(
189
+ new ModuleError(this, error, {
190
+ from: requestShortener.shorten(currentLoader.loader)
191
+ })
192
+ );
163
193
  },
164
194
  exec: (code, filename) => {
165
195
  // @ts-ignore Argument of type 'this' is not assignable to parameter of type 'Module'.
@@ -174,7 +204,9 @@ class NormalModule extends Module {
174
204
  resolver.resolve({}, context, request, {}, callback);
175
205
  },
176
206
  emitFile: (name, content, sourceMap) => {
177
- if (!this.buildInfo.assets) this.buildInfo.assets = Object.create(null);
207
+ if (!this.buildInfo.assets) {
208
+ this.buildInfo.assets = Object.create(null);
209
+ }
178
210
  this.buildInfo.assets[name] = this.createSourceForAsset(
179
211
  name,
180
212
  content,
@@ -191,11 +223,26 @@ class NormalModule extends Module {
191
223
  };
192
224
 
193
225
  compilation.hooks.normalModuleLoader.call(loaderContext, this);
194
- if (options.loader) Object.assign(loaderContext, options.loader);
226
+ if (options.loader) {
227
+ Object.assign(loaderContext, options.loader);
228
+ }
195
229
 
196
230
  return loaderContext;
197
231
  }
198
232
 
233
+ getCurrentLoader(loaderContext, index = loaderContext.loaderIndex) {
234
+ if (
235
+ this.loaders &&
236
+ this.loaders.length &&
237
+ index < this.loaders.length &&
238
+ index >= 0 &&
239
+ this.loaders[index]
240
+ ) {
241
+ return this.loaders[index];
242
+ }
243
+ return null;
244
+ }
245
+
199
246
  createSource(source, resourceBuffer, sourceMap) {
200
247
  // if there is no identifier return raw source
201
248
  if (!this.identifier) {
@@ -249,7 +296,17 @@ class NormalModule extends Module {
249
296
  }
250
297
 
251
298
  if (err) {
252
- const error = new ModuleBuildError(this, err);
299
+ if (!(err instanceof Error)) {
300
+ err = new NonErrorEmittedError(err);
301
+ }
302
+ const currentLoader = this.getCurrentLoader(loaderContext);
303
+ const error = new ModuleBuildError(this, err, {
304
+ from:
305
+ currentLoader &&
306
+ compilation.runtimeTemplate.requestShortener.shorten(
307
+ currentLoader.loader
308
+ )
309
+ });
253
310
  return callback(error);
254
311
  }
255
312
 
@@ -259,10 +316,17 @@ class NormalModule extends Module {
259
316
  const extraInfo = result.result.length >= 2 ? result.result[2] : null;
260
317
 
261
318
  if (!Buffer.isBuffer(source) && typeof source !== "string") {
262
- const error = new ModuleBuildError(
263
- this,
264
- new Error("Final loader didn't return a Buffer or String")
319
+ const currentLoader = this.getCurrentLoader(loaderContext, 0);
320
+ const err = new Error(
321
+ `Final loader (${
322
+ currentLoader
323
+ ? compilation.runtimeTemplate.requestShortener.shorten(
324
+ currentLoader.loader
325
+ )
326
+ : "unknown"
327
+ }) didn't return a Buffer or String`
265
328
  );
329
+ const error = new ModuleBuildError(this, err);
266
330
  return callback(error);
267
331
  }
268
332
 
@@ -4,6 +4,7 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ const path = require("path");
7
8
  const asyncLib = require("neo-async");
8
9
  const {
9
10
  Tapable,
@@ -20,12 +21,21 @@ const cachedMerge = require("./util/cachedMerge");
20
21
 
21
22
  const EMPTY_RESOLVE_OPTIONS = {};
22
23
 
24
+ const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
25
+
23
26
  const loaderToIdent = data => {
24
- if (!data.options) return data.loader;
25
- if (typeof data.options === "string") return data.loader + "?" + data.options;
26
- if (typeof data.options !== "object")
27
+ if (!data.options) {
28
+ return data.loader;
29
+ }
30
+ if (typeof data.options === "string") {
31
+ return data.loader + "?" + data.options;
32
+ }
33
+ if (typeof data.options !== "object") {
27
34
  throw new Error("loader options must be string or object");
28
- if (data.ident) return data.loader + "??" + data.ident;
35
+ }
36
+ if (data.ident) {
37
+ return data.loader + "??" + data.ident;
38
+ }
29
39
  return data.loader + "?" + JSON.stringify(data.options);
30
40
  };
31
41
 
@@ -151,19 +161,33 @@ class NormalModuleFactory extends Tapable {
151
161
  const context = data.context;
152
162
  const request = data.request;
153
163
 
154
- const noPreAutoLoaders = request.startsWith("-!");
155
- const noAutoLoaders = noPreAutoLoaders || request.startsWith("!");
156
- const noPrePostAutoLoaders = request.startsWith("!!");
157
- let elements = request
164
+ const loaderResolver = this.getResolver("loader");
165
+ const normalResolver = this.getResolver("normal", data.resolveOptions);
166
+
167
+ let matchResource = undefined;
168
+ let requestWithoutMatchResource = request;
169
+ const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
170
+ if (matchResourceMatch) {
171
+ matchResource = matchResourceMatch[1];
172
+ if (/^\.\.?\//.test(matchResource)) {
173
+ matchResource = path.join(context, matchResource);
174
+ }
175
+ requestWithoutMatchResource = request.substr(
176
+ matchResourceMatch[0].length
177
+ );
178
+ }
179
+
180
+ const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
181
+ const noAutoLoaders =
182
+ noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
183
+ const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");
184
+ let elements = requestWithoutMatchResource
158
185
  .replace(/^-?!+/, "")
159
186
  .replace(/!!+/g, "!")
160
187
  .split("!");
161
188
  let resource = elements.pop();
162
189
  elements = elements.map(identToLoaderRequest);
163
190
 
164
- const loaderResolver = this.getResolver("loader");
165
- const normalResolver = this.getResolver("normal", data.resolveOptions);
166
-
167
191
  asyncLib.parallel(
168
192
  [
169
193
  callback =>
@@ -227,12 +251,15 @@ class NormalModuleFactory extends Tapable {
227
251
  );
228
252
  }
229
253
 
230
- const userRequest = loaders
231
- .map(loaderToIdent)
232
- .concat([resource])
233
- .join("!");
254
+ const userRequest =
255
+ (matchResource !== undefined ? `${matchResource}!=!` : "") +
256
+ loaders
257
+ .map(loaderToIdent)
258
+ .concat([resource])
259
+ .join("!");
234
260
 
235
- let resourcePath = resource;
261
+ let resourcePath =
262
+ matchResource !== undefined ? matchResource : resource;
236
263
  let resourceQuery = "";
237
264
  const queryIndex = resourcePath.indexOf("?");
238
265
  if (queryIndex >= 0) {
@@ -242,6 +269,10 @@ class NormalModuleFactory extends Tapable {
242
269
 
243
270
  const result = this.ruleSet.exec({
244
271
  resource: resourcePath,
272
+ realResource:
273
+ matchResource !== undefined
274
+ ? resource.replace(/\?.*/, "")
275
+ : resourcePath,
245
276
  resourceQuery,
246
277
  issuer: contextInfo.issuer,
247
278
  compiler: contextInfo.compiler
@@ -252,16 +283,21 @@ class NormalModuleFactory extends Tapable {
252
283
  const useLoadersPre = [];
253
284
  for (const r of result) {
254
285
  if (r.type === "use") {
255
- if (r.enforce === "post" && !noPrePostAutoLoaders)
286
+ if (r.enforce === "post" && !noPrePostAutoLoaders) {
256
287
  useLoadersPost.push(r.value);
257
- else if (
288
+ } else if (
258
289
  r.enforce === "pre" &&
259
290
  !noPreAutoLoaders &&
260
291
  !noPrePostAutoLoaders
261
- )
292
+ ) {
262
293
  useLoadersPre.push(r.value);
263
- else if (!r.enforce && !noAutoLoaders && !noPrePostAutoLoaders)
294
+ } else if (
295
+ !r.enforce &&
296
+ !noAutoLoaders &&
297
+ !noPrePostAutoLoaders
298
+ ) {
264
299
  useLoaders.push(r.value);
300
+ }
265
301
  } else if (
266
302
  typeof r.value === "object" &&
267
303
  r.value !== null &&
@@ -314,6 +350,7 @@ class NormalModuleFactory extends Tapable {
314
350
  rawRequest: request,
315
351
  loaders,
316
352
  resource,
353
+ matchResource,
317
354
  resourceResolveData,
318
355
  settings,
319
356
  type,
@@ -428,8 +465,11 @@ class NormalModuleFactory extends Tapable {
428
465
  getParser(type, parserOptions) {
429
466
  let ident = type;
430
467
  if (parserOptions) {
431
- if (parserOptions.ident) ident = `${type}|${parserOptions.ident}`;
432
- else ident = JSON.stringify([type, parserOptions]);
468
+ if (parserOptions.ident) {
469
+ ident = `${type}|${parserOptions.ident}`;
470
+ } else {
471
+ ident = JSON.stringify([type, parserOptions]);
472
+ }
433
473
  }
434
474
  if (ident in this.parserCache) {
435
475
  return this.parserCache[ident];
@@ -449,8 +489,11 @@ class NormalModuleFactory extends Tapable {
449
489
  getGenerator(type, generatorOptions) {
450
490
  let ident = type;
451
491
  if (generatorOptions) {
452
- if (generatorOptions.ident) ident = `${type}|${generatorOptions.ident}`;
453
- else ident = JSON.stringify([type, generatorOptions]);
492
+ if (generatorOptions.ident) {
493
+ ident = `${type}|${generatorOptions.ident}`;
494
+ } else {
495
+ ident = JSON.stringify([type, generatorOptions]);
496
+ }
454
497
  }
455
498
  if (ident in this.generatorCache) {
456
499
  return this.generatorCache[ident];
@@ -36,8 +36,9 @@ class OptionsDefaulter {
36
36
  for (let name in this.defaults) {
37
37
  switch (this.config[name]) {
38
38
  case undefined:
39
- if (getProperty(options, name) === undefined)
39
+ if (getProperty(options, name) === undefined) {
40
40
  setProperty(options, name, this.defaults[name]);
41
+ }
41
42
  break;
42
43
  case "call":
43
44
  setProperty(
@@ -47,12 +48,15 @@ class OptionsDefaulter {
47
48
  );
48
49
  break;
49
50
  case "make":
50
- if (getProperty(options, name) === undefined)
51
+ if (getProperty(options, name) === undefined) {
51
52
  setProperty(options, name, this.defaults[name].call(this, options));
53
+ }
52
54
  break;
53
55
  case "append": {
54
56
  let oldValue = getProperty(options, name);
55
- if (!Array.isArray(oldValue)) oldValue = [];
57
+ if (!Array.isArray(oldValue)) {
58
+ oldValue = [];
59
+ }
56
60
  oldValue.push(...this.defaults[name]);
57
61
  setProperty(options, name, oldValue);
58
62
  break;