webpack 4.1.0 → 4.4.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/README.md +719 -721
  2. package/bin/webpack.js +69 -10
  3. package/lib/APIPlugin.js +84 -84
  4. package/lib/AmdMainTemplatePlugin.js +75 -77
  5. package/lib/AsyncDependencyToInitialChunkError.js +21 -23
  6. package/lib/BannerPlugin.js +101 -101
  7. package/lib/Chunk.js +477 -469
  8. package/lib/ChunkTemplate.js +51 -53
  9. package/lib/Compilation.js +1858 -1851
  10. package/lib/Compiler.js +493 -478
  11. package/lib/ConcurrentCompilationError.js +19 -0
  12. package/lib/ContextModule.js +696 -685
  13. package/lib/ContextModuleFactory.js +245 -243
  14. package/lib/DefinePlugin.js +197 -197
  15. package/lib/DelegatedModule.js +101 -101
  16. package/lib/DependenciesBlockVariable.js +51 -52
  17. package/lib/Dependency.js +53 -52
  18. package/lib/DllModule.js +54 -54
  19. package/lib/DllModuleFactory.js +29 -29
  20. package/lib/EnvironmentPlugin.js +65 -67
  21. package/lib/EvalDevToolModuleTemplatePlugin.js +60 -60
  22. package/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +105 -105
  23. package/lib/ExportPropertyMainTemplatePlugin.js +40 -40
  24. package/lib/ExternalModule.js +159 -159
  25. package/lib/FunctionModuleTemplatePlugin.js +98 -98
  26. package/lib/HotModuleReplacement.runtime.js +631 -631
  27. package/lib/HotModuleReplacementPlugin.js +407 -406
  28. package/lib/HotUpdateChunkTemplate.js +78 -80
  29. package/lib/JavascriptGenerator.js +228 -229
  30. package/lib/JavascriptModulesPlugin.js +184 -158
  31. package/lib/JsonGenerator.js +42 -42
  32. package/lib/MainTemplate.js +406 -402
  33. package/lib/Module.js +343 -340
  34. package/lib/ModuleBuildError.js +42 -42
  35. package/lib/ModuleError.js +28 -28
  36. package/lib/ModuleFilenameHelpers.js +166 -166
  37. package/lib/ModuleTemplate.js +77 -79
  38. package/lib/ModuleWarning.js +30 -30
  39. package/lib/MultiCompiler.js +271 -259
  40. package/lib/MultiModule.js +78 -75
  41. package/lib/MultiModuleFactory.js +23 -23
  42. package/lib/MultiWatching.js +38 -37
  43. package/lib/NoModeWarning.js +23 -21
  44. package/lib/NormalModule.js +478 -470
  45. package/lib/NormalModuleFactory.js +483 -481
  46. package/lib/OptionsDefaulter.js +80 -86
  47. package/lib/Parser.js +2074 -2071
  48. package/lib/ProgressPlugin.js +231 -231
  49. package/lib/RawModule.js +54 -55
  50. package/lib/RecordIdsPlugin.js +160 -160
  51. package/lib/RemovedPluginError.js +13 -13
  52. package/lib/ResolverFactory.js +64 -67
  53. package/lib/RuntimeTemplate.js +267 -297
  54. package/lib/SetVarMainTemplatePlugin.js +57 -57
  55. package/lib/SourceMapDevToolPlugin.js +302 -308
  56. package/lib/Stats.js +1234 -1212
  57. package/lib/Template.js +205 -205
  58. package/lib/TemplatedPathPlugin.js +170 -143
  59. package/lib/UmdMainTemplatePlugin.js +264 -269
  60. package/lib/Watching.js +193 -193
  61. package/lib/WebAssemblyParser.js +50 -54
  62. package/lib/WebpackOptionsApply.js +401 -401
  63. package/lib/WebpackOptionsDefaulter.js +337 -317
  64. package/lib/WebpackOptionsValidationError.js +316 -319
  65. package/lib/debug/ProfilingPlugin.js +409 -405
  66. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +328 -311
  67. package/lib/dependencies/AMDRequireContextDependency.js +20 -20
  68. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +270 -241
  69. package/lib/dependencies/HarmonyAcceptImportDependency.js +23 -23
  70. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +620 -606
  71. package/lib/dependencies/HarmonyExportSpecifierDependency.js +53 -53
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +214 -214
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +154 -156
  74. package/lib/dependencies/ImportDependenciesBlock.js +17 -17
  75. package/lib/dependencies/ImportDependency.js +34 -34
  76. package/lib/dependencies/ImportEagerDependency.js +32 -32
  77. package/lib/dependencies/ImportParserPlugin.js +175 -179
  78. package/lib/dependencies/ImportWeakDependency.js +34 -34
  79. package/lib/dependencies/JsonExportsDependency.js +25 -25
  80. package/lib/dependencies/ModuleDependency.js +20 -20
  81. package/lib/dependencies/NullDependency.js +20 -20
  82. package/lib/dependencies/RequireContextDependency.js +22 -22
  83. package/lib/dependencies/RequireIncludeDependency.js +40 -40
  84. package/lib/dependencies/WebpackMissingModule.js +20 -22
  85. package/lib/node/NodeChunkTemplatePlugin.js +31 -31
  86. package/lib/node/NodeHotUpdateChunkTemplatePlugin.js +36 -36
  87. package/lib/node/NodeMainTemplatePlugin.js +320 -273
  88. package/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +113 -115
  89. package/lib/optimize/AggressiveSplittingPlugin.js +281 -281
  90. package/lib/optimize/ConcatenatedModule.js +1364 -1366
  91. package/lib/optimize/RemoveParentModulesPlugin.js +114 -114
  92. package/lib/optimize/SplitChunksPlugin.js +519 -491
  93. package/lib/performance/SizeLimitsPlugin.js +105 -105
  94. package/lib/util/TrackingSet.js +35 -35
  95. package/lib/util/objectToMap.js +10 -10
  96. package/lib/wasm/WasmModuleTemplatePlugin.js +106 -106
  97. package/lib/web/JsonpChunkTemplatePlugin.js +47 -47
  98. package/lib/web/JsonpExportMainTemplatePlugin.js +47 -47
  99. package/lib/web/JsonpHotUpdateChunkTemplatePlugin.js +39 -39
  100. package/lib/web/JsonpMainTemplatePlugin.js +425 -403
  101. package/lib/webpack.js +182 -179
  102. package/lib/webworker/WebWorkerChunkTemplatePlugin.js +35 -35
  103. package/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +40 -40
  104. package/lib/webworker/WebWorkerMainTemplatePlugin.js +177 -154
  105. package/package.json +9 -8
  106. package/schemas/WebpackOptions.json +1973 -1951
  107. package/schemas/ajv.absolutePath.js +55 -29
  108. package/schemas/plugins/BannerPlugin.json +85 -85
  109. package/schemas/plugins/DllPlugin.json +28 -28
  110. package/schemas/plugins/DllReferencePlugin.json +99 -99
  111. package/schemas/plugins/HashedModuleIdsPlugin.json +24 -24
  112. package/schemas/plugins/LoaderOptionsPlugin.json +26 -26
  113. package/schemas/plugins/SourceMapDevToolPlugin.json +187 -187
  114. package/schemas/plugins/WatchIgnorePlugin.json +16 -16
  115. package/schemas/plugins/debug/ProfilingPlugin.json +12 -12
  116. package/schemas/plugins/optimize/AggressiveSplittingPlugin.json +22 -22
  117. package/schemas/plugins/optimize/LimitChunkCountPlugin.json +15 -15
  118. package/schemas/plugins/optimize/MinChunkSizePlugin.json +13 -13
package/lib/Compiler.js CHANGED
@@ -1,478 +1,493 @@
1
- /*
2
- MIT License http://www.opensource.org/licenses/mit-license.php
3
- Author Tobias Koppers @sokra
4
- */
5
- "use strict";
6
-
7
- const asyncLib = require("neo-async");
8
- const path = require("path");
9
- const util = require("util");
10
- const Tapable = require("tapable").Tapable;
11
- const SyncHook = require("tapable").SyncHook;
12
- const SyncBailHook = require("tapable").SyncBailHook;
13
- const AsyncParallelHook = require("tapable").AsyncParallelHook;
14
- const AsyncSeriesHook = require("tapable").AsyncSeriesHook;
15
-
16
- const Compilation = require("./Compilation");
17
- const Stats = require("./Stats");
18
- const Watching = require("./Watching");
19
- const NormalModuleFactory = require("./NormalModuleFactory");
20
- const ContextModuleFactory = require("./ContextModuleFactory");
21
- const ResolverFactory = require("./ResolverFactory");
22
-
23
- const RequestShortener = require("./RequestShortener");
24
- const makePathsRelative = require("./util/identifier").makePathsRelative;
25
-
26
- class Compiler extends Tapable {
27
- constructor(context) {
28
- super();
29
- this.hooks = {
30
- shouldEmit: new SyncBailHook(["compilation"]),
31
- done: new AsyncSeriesHook(["stats"]),
32
- additionalPass: new AsyncSeriesHook([]),
33
- beforeRun: new AsyncSeriesHook(["compilation"]),
34
- run: new AsyncSeriesHook(["compilation"]),
35
- emit: new AsyncSeriesHook(["compilation"]),
36
- afterEmit: new AsyncSeriesHook(["compilation"]),
37
- thisCompilation: new SyncHook(["compilation", "params"]),
38
- compilation: new SyncHook(["compilation", "params"]),
39
- normalModuleFactory: new SyncHook(["normalModuleFactory"]),
40
- contextModuleFactory: new SyncHook(["contextModulefactory"]),
41
- beforeCompile: new AsyncSeriesHook(["params"]),
42
- compile: new SyncHook(["params"]),
43
- make: new AsyncParallelHook(["compilation"]),
44
- afterCompile: new AsyncSeriesHook(["compilation"]),
45
- watchRun: new AsyncSeriesHook(["compiler"]),
46
- failed: new SyncHook(["error"]),
47
- invalid: new SyncHook(["filename", "changeTime"]),
48
- watchClose: new SyncHook([]),
49
-
50
- // TODO the following hooks are weirdly located here
51
- // TODO move them for webpack 5
52
- environment: new SyncHook([]),
53
- afterEnvironment: new SyncHook([]),
54
- afterPlugins: new SyncHook(["compiler"]),
55
- afterResolvers: new SyncHook(["compiler"]),
56
- entryOption: new SyncBailHook(["context", "entry"])
57
- };
58
- this._pluginCompat.tap("Compiler", options => {
59
- switch (options.name) {
60
- case "additional-pass":
61
- case "before-run":
62
- case "run":
63
- case "emit":
64
- case "after-emit":
65
- case "before-compile":
66
- case "make":
67
- case "after-compile":
68
- case "watch-run":
69
- options.async = true;
70
- break;
71
- }
72
- });
73
-
74
- this.outputPath = "";
75
- this.outputFileSystem = null;
76
- this.inputFileSystem = null;
77
-
78
- this.recordsInputPath = null;
79
- this.recordsOutputPath = null;
80
- this.records = {};
81
-
82
- this.fileTimestamps = new Map();
83
- this.contextTimestamps = new Map();
84
-
85
- this.resolverFactory = new ResolverFactory();
86
-
87
- // TODO remove in webpack 5
88
- this.resolvers = {
89
- normal: {
90
- plugins: util.deprecate((hook, fn) => {
91
- this.resolverFactory.plugin("resolver normal", resolver => {
92
- resolver.plugin(hook, fn);
93
- });
94
- }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
95
- apply: util.deprecate((...args) => {
96
- this.resolverFactory.plugin("resolver normal", resolver => {
97
- resolver.apply(...args);
98
- });
99
- }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
100
- },
101
- loader: {
102
- plugins: util.deprecate((hook, fn) => {
103
- this.resolverFactory.plugin("resolver loader", resolver => {
104
- resolver.plugin(hook, fn);
105
- });
106
- }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
107
- apply: util.deprecate((...args) => {
108
- this.resolverFactory.plugin("resolver loader", resolver => {
109
- resolver.apply(...args);
110
- });
111
- }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
112
- },
113
- context: {
114
- plugins: util.deprecate((hook, fn) => {
115
- this.resolverFactory.plugin("resolver context", resolver => {
116
- resolver.plugin(hook, fn);
117
- });
118
- }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
119
- apply: util.deprecate((...args) => {
120
- this.resolverFactory.plugin("resolver context", resolver => {
121
- resolver.apply(...args);
122
- });
123
- }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
124
- }
125
- };
126
-
127
- this.options = {};
128
-
129
- this.context = context;
130
-
131
- this.requestShortener = new RequestShortener(context);
132
- }
133
-
134
- watch(watchOptions, handler) {
135
- this.fileTimestamps = new Map();
136
- this.contextTimestamps = new Map();
137
- return new Watching(this, watchOptions, handler);
138
- }
139
-
140
- run(callback) {
141
- const startTime = Date.now();
142
-
143
- const onCompiled = (err, compilation) => {
144
- if (err) return callback(err);
145
-
146
- if (this.hooks.shouldEmit.call(compilation) === false) {
147
- const stats = new Stats(compilation);
148
- stats.startTime = startTime;
149
- stats.endTime = Date.now();
150
- this.hooks.done.callAsync(stats, err => {
151
- if (err) return callback(err);
152
- return callback(null, stats);
153
- });
154
- return;
155
- }
156
-
157
- this.emitAssets(compilation, err => {
158
- if (err) return callback(err);
159
-
160
- if (compilation.hooks.needAdditionalPass.call()) {
161
- compilation.needAdditionalPass = true;
162
-
163
- const stats = new Stats(compilation);
164
- stats.startTime = startTime;
165
- stats.endTime = Date.now();
166
- this.hooks.done.callAsync(stats, err => {
167
- if (err) return callback(err);
168
-
169
- this.hooks.additionalPass.callAsync(err => {
170
- if (err) return callback(err);
171
- this.compile(onCompiled);
172
- });
173
- });
174
- return;
175
- }
176
-
177
- this.emitRecords(err => {
178
- if (err) return callback(err);
179
-
180
- const stats = new Stats(compilation);
181
- stats.startTime = startTime;
182
- stats.endTime = Date.now();
183
- this.hooks.done.callAsync(stats, err => {
184
- if (err) return callback(err);
185
- return callback(null, stats);
186
- });
187
- });
188
- });
189
- };
190
-
191
- this.hooks.beforeRun.callAsync(this, err => {
192
- if (err) return callback(err);
193
-
194
- this.hooks.run.callAsync(this, err => {
195
- if (err) return callback(err);
196
-
197
- this.readRecords(err => {
198
- if (err) return callback(err);
199
-
200
- this.compile(onCompiled);
201
- });
202
- });
203
- });
204
- }
205
-
206
- runAsChild(callback) {
207
- this.compile((err, compilation) => {
208
- if (err) return callback(err);
209
-
210
- this.parentCompilation.children.push(compilation);
211
- for (const name of Object.keys(compilation.assets)) {
212
- this.parentCompilation.assets[name] = compilation.assets[name];
213
- }
214
-
215
- const entries = Array.from(
216
- compilation.entrypoints.values(),
217
- ep => ep.chunks
218
- ).reduce((array, chunks) => {
219
- return array.concat(chunks);
220
- }, []);
221
-
222
- return callback(null, entries, compilation);
223
- });
224
- }
225
-
226
- purgeInputFileSystem() {
227
- if (this.inputFileSystem && this.inputFileSystem.purge)
228
- this.inputFileSystem.purge();
229
- }
230
-
231
- emitAssets(compilation, callback) {
232
- let outputPath;
233
-
234
- const emitFiles = err => {
235
- if (err) return callback(err);
236
-
237
- asyncLib.forEach(
238
- compilation.assets,
239
- (source, file, callback) => {
240
- let targetFile = file;
241
- const queryStringIdx = targetFile.indexOf("?");
242
- if (queryStringIdx >= 0) {
243
- targetFile = targetFile.substr(0, queryStringIdx);
244
- }
245
-
246
- const writeOut = err => {
247
- if (err) return callback(err);
248
- const targetPath = this.outputFileSystem.join(
249
- outputPath,
250
- targetFile
251
- );
252
- if (source.existsAt === targetPath) {
253
- source.emitted = false;
254
- return callback();
255
- }
256
- let content = source.source();
257
-
258
- if (!Buffer.isBuffer(content)) {
259
- content = Buffer.from(content, "utf8");
260
- }
261
-
262
- source.existsAt = targetPath;
263
- source.emitted = true;
264
- this.outputFileSystem.writeFile(targetPath, content, callback);
265
- };
266
-
267
- if (targetFile.match(/\/|\\/)) {
268
- const dir = path.dirname(targetFile);
269
- this.outputFileSystem.mkdirp(
270
- this.outputFileSystem.join(outputPath, dir),
271
- writeOut
272
- );
273
- } else writeOut();
274
- },
275
- err => {
276
- if (err) return callback(err);
277
-
278
- this.hooks.afterEmit.callAsync(compilation, err => {
279
- if (err) return callback(err);
280
-
281
- return callback();
282
- });
283
- }
284
- );
285
- };
286
-
287
- this.hooks.emit.callAsync(compilation, err => {
288
- if (err) return callback(err);
289
- outputPath = compilation.getPath(this.outputPath);
290
- this.outputFileSystem.mkdirp(outputPath, emitFiles);
291
- });
292
- }
293
-
294
- emitRecords(callback) {
295
- if (!this.recordsOutputPath) return callback();
296
- const idx1 = this.recordsOutputPath.lastIndexOf("/");
297
- const idx2 = this.recordsOutputPath.lastIndexOf("\\");
298
- let recordsOutputPathDirectory = null;
299
- if (idx1 > idx2)
300
- recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
301
- if (idx1 < idx2)
302
- recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
303
-
304
- const writeFile = () => {
305
- this.outputFileSystem.writeFile(
306
- this.recordsOutputPath,
307
- JSON.stringify(this.records, undefined, 2),
308
- callback
309
- );
310
- };
311
-
312
- if (!recordsOutputPathDirectory) return writeFile();
313
- this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
314
- if (err) return callback(err);
315
- writeFile();
316
- });
317
- }
318
-
319
- readRecords(callback) {
320
- if (!this.recordsInputPath) {
321
- this.records = {};
322
- return callback();
323
- }
324
- this.inputFileSystem.stat(this.recordsInputPath, err => {
325
- // It doesn't exist
326
- // We can ignore this.
327
- if (err) return callback();
328
-
329
- this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => {
330
- if (err) return callback(err);
331
-
332
- try {
333
- this.records = JSON.parse(content.toString("utf-8"));
334
- } catch (e) {
335
- e.message = "Cannot parse records: " + e.message;
336
- return callback(e);
337
- }
338
-
339
- return callback();
340
- });
341
- });
342
- }
343
-
344
- createChildCompiler(
345
- compilation,
346
- compilerName,
347
- compilerIndex,
348
- outputOptions,
349
- plugins
350
- ) {
351
- const childCompiler = new Compiler(this.context);
352
- if (Array.isArray(plugins)) {
353
- for (const plugin of plugins) plugin.apply(childCompiler);
354
- }
355
- for (const name in this.hooks) {
356
- if (
357
- ![
358
- "make",
359
- "compile",
360
- "emit",
361
- "afterEmit",
362
- "invalid",
363
- "done",
364
- "thisCompilation"
365
- ].includes(name)
366
- ) {
367
- if (childCompiler.hooks[name])
368
- childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
369
- }
370
- }
371
- childCompiler.name = compilerName;
372
- childCompiler.outputPath = this.outputPath;
373
- childCompiler.inputFileSystem = this.inputFileSystem;
374
- childCompiler.outputFileSystem = null;
375
- childCompiler.resolverFactory = this.resolverFactory;
376
- childCompiler.fileTimestamps = this.fileTimestamps;
377
- childCompiler.contextTimestamps = this.contextTimestamps;
378
-
379
- const relativeCompilerName = makePathsRelative(this.context, compilerName);
380
- if (!this.records[relativeCompilerName])
381
- this.records[relativeCompilerName] = [];
382
- if (this.records[relativeCompilerName][compilerIndex])
383
- childCompiler.records = this.records[relativeCompilerName][compilerIndex];
384
- else this.records[relativeCompilerName].push((childCompiler.records = {}));
385
-
386
- childCompiler.options = Object.create(this.options);
387
- childCompiler.options.output = Object.create(childCompiler.options.output);
388
- for (const name in outputOptions) {
389
- childCompiler.options.output[name] = outputOptions[name];
390
- }
391
- childCompiler.parentCompilation = compilation;
392
-
393
- compilation.hooks.childCompiler.call(
394
- childCompiler,
395
- compilerName,
396
- compilerIndex
397
- );
398
-
399
- return childCompiler;
400
- }
401
-
402
- isChild() {
403
- return !!this.parentCompilation;
404
- }
405
-
406
- createCompilation() {
407
- return new Compilation(this);
408
- }
409
-
410
- newCompilation(params) {
411
- const compilation = this.createCompilation();
412
- compilation.fileTimestamps = this.fileTimestamps;
413
- compilation.contextTimestamps = this.contextTimestamps;
414
- compilation.name = this.name;
415
- compilation.records = this.records;
416
- compilation.compilationDependencies = params.compilationDependencies;
417
- this.hooks.thisCompilation.call(compilation, params);
418
- this.hooks.compilation.call(compilation, params);
419
- return compilation;
420
- }
421
-
422
- createNormalModuleFactory() {
423
- const normalModuleFactory = new NormalModuleFactory(
424
- this.options.context,
425
- this.resolverFactory,
426
- this.options.module || {}
427
- );
428
- this.hooks.normalModuleFactory.call(normalModuleFactory);
429
- return normalModuleFactory;
430
- }
431
-
432
- createContextModuleFactory() {
433
- const contextModuleFactory = new ContextModuleFactory(
434
- this.resolverFactory,
435
- this.inputFileSystem
436
- );
437
- this.hooks.contextModuleFactory.call(contextModuleFactory);
438
- return contextModuleFactory;
439
- }
440
-
441
- newCompilationParams() {
442
- const params = {
443
- normalModuleFactory: this.createNormalModuleFactory(),
444
- contextModuleFactory: this.createContextModuleFactory(),
445
- compilationDependencies: new Set()
446
- };
447
- return params;
448
- }
449
-
450
- compile(callback) {
451
- const params = this.newCompilationParams();
452
- this.hooks.beforeCompile.callAsync(params, err => {
453
- if (err) return callback(err);
454
-
455
- this.hooks.compile.call(params);
456
-
457
- const compilation = this.newCompilation(params);
458
-
459
- this.hooks.make.callAsync(compilation, err => {
460
- if (err) return callback(err);
461
-
462
- compilation.finish();
463
-
464
- compilation.seal(err => {
465
- if (err) return callback(err);
466
-
467
- this.hooks.afterCompile.callAsync(compilation, err => {
468
- if (err) return callback(err);
469
-
470
- return callback(null, compilation);
471
- });
472
- });
473
- });
474
- });
475
- }
476
- }
477
-
478
- module.exports = Compiler;
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+ "use strict";
6
+
7
+ const asyncLib = require("neo-async");
8
+ const path = require("path");
9
+ const util = require("util");
10
+ const {
11
+ Tapable,
12
+ SyncHook,
13
+ SyncBailHook,
14
+ AsyncParallelHook,
15
+ AsyncSeriesHook
16
+ } = require("tapable");
17
+
18
+ const Compilation = require("./Compilation");
19
+ const Stats = require("./Stats");
20
+ const Watching = require("./Watching");
21
+ const NormalModuleFactory = require("./NormalModuleFactory");
22
+ const ContextModuleFactory = require("./ContextModuleFactory");
23
+ const ResolverFactory = require("./ResolverFactory");
24
+
25
+ const RequestShortener = require("./RequestShortener");
26
+ const { makePathsRelative } = require("./util/identifier");
27
+ const ConcurrentCompilationError = require("./ConcurrentCompilationError");
28
+
29
+ class Compiler extends Tapable {
30
+ constructor(context) {
31
+ super();
32
+ this.hooks = {
33
+ shouldEmit: new SyncBailHook(["compilation"]),
34
+ done: new AsyncSeriesHook(["stats"]),
35
+ additionalPass: new AsyncSeriesHook([]),
36
+ beforeRun: new AsyncSeriesHook(["compilation"]),
37
+ run: new AsyncSeriesHook(["compilation"]),
38
+ emit: new AsyncSeriesHook(["compilation"]),
39
+ afterEmit: new AsyncSeriesHook(["compilation"]),
40
+ thisCompilation: new SyncHook(["compilation", "params"]),
41
+ compilation: new SyncHook(["compilation", "params"]),
42
+ normalModuleFactory: new SyncHook(["normalModuleFactory"]),
43
+ contextModuleFactory: new SyncHook(["contextModulefactory"]),
44
+ beforeCompile: new AsyncSeriesHook(["params"]),
45
+ compile: new SyncHook(["params"]),
46
+ make: new AsyncParallelHook(["compilation"]),
47
+ afterCompile: new AsyncSeriesHook(["compilation"]),
48
+ watchRun: new AsyncSeriesHook(["compiler"]),
49
+ failed: new SyncHook(["error"]),
50
+ invalid: new SyncHook(["filename", "changeTime"]),
51
+ watchClose: new SyncHook([]),
52
+
53
+ // TODO the following hooks are weirdly located here
54
+ // TODO move them for webpack 5
55
+ environment: new SyncHook([]),
56
+ afterEnvironment: new SyncHook([]),
57
+ afterPlugins: new SyncHook(["compiler"]),
58
+ afterResolvers: new SyncHook(["compiler"]),
59
+ entryOption: new SyncBailHook(["context", "entry"])
60
+ };
61
+ this._pluginCompat.tap("Compiler", options => {
62
+ switch (options.name) {
63
+ case "additional-pass":
64
+ case "before-run":
65
+ case "run":
66
+ case "emit":
67
+ case "after-emit":
68
+ case "before-compile":
69
+ case "make":
70
+ case "after-compile":
71
+ case "watch-run":
72
+ options.async = true;
73
+ break;
74
+ }
75
+ });
76
+
77
+ this.outputPath = "";
78
+ this.outputFileSystem = null;
79
+ this.inputFileSystem = null;
80
+
81
+ this.recordsInputPath = null;
82
+ this.recordsOutputPath = null;
83
+ this.records = {};
84
+
85
+ this.fileTimestamps = new Map();
86
+ this.contextTimestamps = new Map();
87
+
88
+ this.resolverFactory = new ResolverFactory();
89
+
90
+ // TODO remove in webpack 5
91
+ this.resolvers = {
92
+ normal: {
93
+ plugins: util.deprecate((hook, fn) => {
94
+ this.resolverFactory.plugin("resolver normal", resolver => {
95
+ resolver.plugin(hook, fn);
96
+ });
97
+ }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* … */);\n}); instead.'),
98
+ apply: util.deprecate((...args) => {
99
+ this.resolverFactory.plugin("resolver normal", resolver => {
100
+ resolver.apply(...args);
101
+ });
102
+ }, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* … */);\n}); instead.')
103
+ },
104
+ loader: {
105
+ plugins: util.deprecate((hook, fn) => {
106
+ this.resolverFactory.plugin("resolver loader", resolver => {
107
+ resolver.plugin(hook, fn);
108
+ });
109
+ }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* … */);\n}); instead.'),
110
+ apply: util.deprecate((...args) => {
111
+ this.resolverFactory.plugin("resolver loader", resolver => {
112
+ resolver.apply(...args);
113
+ });
114
+ }, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* … */);\n}); instead.')
115
+ },
116
+ context: {
117
+ plugins: util.deprecate((hook, fn) => {
118
+ this.resolverFactory.plugin("resolver context", resolver => {
119
+ resolver.plugin(hook, fn);
120
+ });
121
+ }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* … */);\n}); instead.'),
122
+ apply: util.deprecate((...args) => {
123
+ this.resolverFactory.plugin("resolver context", resolver => {
124
+ resolver.apply(...args);
125
+ });
126
+ }, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* … */);\n}); instead.')
127
+ }
128
+ };
129
+
130
+ this.options = {};
131
+
132
+ this.context = context;
133
+
134
+ this.requestShortener = new RequestShortener(context);
135
+
136
+ this.running = false;
137
+ }
138
+
139
+ watch(watchOptions, handler) {
140
+ if (this.running) return handler(new ConcurrentCompilationError());
141
+
142
+ this.running = true;
143
+ this.fileTimestamps = new Map();
144
+ this.contextTimestamps = new Map();
145
+ return new Watching(this, watchOptions, handler);
146
+ }
147
+
148
+ run(callback) {
149
+ if (this.running) return callback(new ConcurrentCompilationError());
150
+
151
+ const finalCallback = (err, stats) => {
152
+ this.running = false;
153
+
154
+ if (callback !== undefined) return callback(err, stats);
155
+ };
156
+
157
+ const startTime = Date.now();
158
+
159
+ this.running = true;
160
+
161
+ const onCompiled = (err, compilation) => {
162
+ if (err) return finalCallback(err);
163
+
164
+ if (this.hooks.shouldEmit.call(compilation) === false) {
165
+ const stats = new Stats(compilation);
166
+ stats.startTime = startTime;
167
+ stats.endTime = Date.now();
168
+ this.hooks.done.callAsync(stats, err => {
169
+ if (err) return finalCallback(err);
170
+ return finalCallback(null, stats);
171
+ });
172
+ return;
173
+ }
174
+
175
+ this.emitAssets(compilation, err => {
176
+ if (err) return finalCallback(err);
177
+
178
+ if (compilation.hooks.needAdditionalPass.call()) {
179
+ compilation.needAdditionalPass = true;
180
+
181
+ const stats = new Stats(compilation);
182
+ stats.startTime = startTime;
183
+ stats.endTime = Date.now();
184
+ this.hooks.done.callAsync(stats, err => {
185
+ if (err) return finalCallback(err);
186
+
187
+ this.hooks.additionalPass.callAsync(err => {
188
+ if (err) return finalCallback(err);
189
+ this.compile(onCompiled);
190
+ });
191
+ });
192
+ return;
193
+ }
194
+
195
+ this.emitRecords(err => {
196
+ if (err) return finalCallback(err);
197
+
198
+ const stats = new Stats(compilation);
199
+ stats.startTime = startTime;
200
+ stats.endTime = Date.now();
201
+ this.hooks.done.callAsync(stats, err => {
202
+ if (err) return finalCallback(err);
203
+ return finalCallback(null, stats);
204
+ });
205
+ });
206
+ });
207
+ };
208
+
209
+ this.hooks.beforeRun.callAsync(this, err => {
210
+ if (err) return finalCallback(err);
211
+
212
+ this.hooks.run.callAsync(this, err => {
213
+ if (err) return finalCallback(err);
214
+
215
+ this.readRecords(err => {
216
+ if (err) return finalCallback(err);
217
+
218
+ this.compile(onCompiled);
219
+ });
220
+ });
221
+ });
222
+ }
223
+
224
+ runAsChild(callback) {
225
+ this.compile((err, compilation) => {
226
+ if (err) return callback(err);
227
+
228
+ this.parentCompilation.children.push(compilation);
229
+ for (const name of Object.keys(compilation.assets)) {
230
+ this.parentCompilation.assets[name] = compilation.assets[name];
231
+ }
232
+
233
+ const entries = Array.from(
234
+ compilation.entrypoints.values(),
235
+ ep => ep.chunks
236
+ ).reduce((array, chunks) => {
237
+ return array.concat(chunks);
238
+ }, []);
239
+
240
+ return callback(null, entries, compilation);
241
+ });
242
+ }
243
+
244
+ purgeInputFileSystem() {
245
+ if (this.inputFileSystem && this.inputFileSystem.purge)
246
+ this.inputFileSystem.purge();
247
+ }
248
+
249
+ emitAssets(compilation, callback) {
250
+ let outputPath;
251
+
252
+ const emitFiles = err => {
253
+ if (err) return callback(err);
254
+
255
+ asyncLib.forEach(
256
+ compilation.assets,
257
+ (source, file, callback) => {
258
+ let targetFile = file;
259
+ const queryStringIdx = targetFile.indexOf("?");
260
+ if (queryStringIdx >= 0) {
261
+ targetFile = targetFile.substr(0, queryStringIdx);
262
+ }
263
+
264
+ const writeOut = err => {
265
+ if (err) return callback(err);
266
+ const targetPath = this.outputFileSystem.join(
267
+ outputPath,
268
+ targetFile
269
+ );
270
+ if (source.existsAt === targetPath) {
271
+ source.emitted = false;
272
+ return callback();
273
+ }
274
+ let content = source.source();
275
+
276
+ if (!Buffer.isBuffer(content)) {
277
+ content = Buffer.from(content, "utf8");
278
+ }
279
+
280
+ source.existsAt = targetPath;
281
+ source.emitted = true;
282
+ this.outputFileSystem.writeFile(targetPath, content, callback);
283
+ };
284
+
285
+ if (targetFile.match(/\/|\\/)) {
286
+ const dir = path.dirname(targetFile);
287
+ this.outputFileSystem.mkdirp(
288
+ this.outputFileSystem.join(outputPath, dir),
289
+ writeOut
290
+ );
291
+ } else writeOut();
292
+ },
293
+ err => {
294
+ if (err) return callback(err);
295
+
296
+ this.hooks.afterEmit.callAsync(compilation, err => {
297
+ if (err) return callback(err);
298
+
299
+ return callback();
300
+ });
301
+ }
302
+ );
303
+ };
304
+
305
+ this.hooks.emit.callAsync(compilation, err => {
306
+ if (err) return callback(err);
307
+ outputPath = compilation.getPath(this.outputPath);
308
+ this.outputFileSystem.mkdirp(outputPath, emitFiles);
309
+ });
310
+ }
311
+
312
+ emitRecords(callback) {
313
+ if (!this.recordsOutputPath) return callback();
314
+ const idx1 = this.recordsOutputPath.lastIndexOf("/");
315
+ const idx2 = this.recordsOutputPath.lastIndexOf("\\");
316
+ let recordsOutputPathDirectory = null;
317
+ if (idx1 > idx2)
318
+ recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
319
+ if (idx1 < idx2)
320
+ recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
321
+
322
+ const writeFile = () => {
323
+ this.outputFileSystem.writeFile(
324
+ this.recordsOutputPath,
325
+ JSON.stringify(this.records, undefined, 2),
326
+ callback
327
+ );
328
+ };
329
+
330
+ if (!recordsOutputPathDirectory) return writeFile();
331
+ this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
332
+ if (err) return callback(err);
333
+ writeFile();
334
+ });
335
+ }
336
+
337
+ readRecords(callback) {
338
+ if (!this.recordsInputPath) {
339
+ this.records = {};
340
+ return callback();
341
+ }
342
+ this.inputFileSystem.stat(this.recordsInputPath, err => {
343
+ // It doesn't exist
344
+ // We can ignore this.
345
+ if (err) return callback();
346
+
347
+ this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => {
348
+ if (err) return callback(err);
349
+
350
+ try {
351
+ this.records = JSON.parse(content.toString("utf-8"));
352
+ } catch (e) {
353
+ e.message = "Cannot parse records: " + e.message;
354
+ return callback(e);
355
+ }
356
+
357
+ return callback();
358
+ });
359
+ });
360
+ }
361
+
362
+ createChildCompiler(
363
+ compilation,
364
+ compilerName,
365
+ compilerIndex,
366
+ outputOptions,
367
+ plugins
368
+ ) {
369
+ const childCompiler = new Compiler(this.context);
370
+ if (Array.isArray(plugins)) {
371
+ for (const plugin of plugins) plugin.apply(childCompiler);
372
+ }
373
+ for (const name in this.hooks) {
374
+ if (
375
+ ![
376
+ "make",
377
+ "compile",
378
+ "emit",
379
+ "afterEmit",
380
+ "invalid",
381
+ "done",
382
+ "thisCompilation"
383
+ ].includes(name)
384
+ ) {
385
+ if (childCompiler.hooks[name])
386
+ childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
387
+ }
388
+ }
389
+ childCompiler.name = compilerName;
390
+ childCompiler.outputPath = this.outputPath;
391
+ childCompiler.inputFileSystem = this.inputFileSystem;
392
+ childCompiler.outputFileSystem = null;
393
+ childCompiler.resolverFactory = this.resolverFactory;
394
+ childCompiler.fileTimestamps = this.fileTimestamps;
395
+ childCompiler.contextTimestamps = this.contextTimestamps;
396
+
397
+ const relativeCompilerName = makePathsRelative(this.context, compilerName);
398
+ if (!this.records[relativeCompilerName])
399
+ this.records[relativeCompilerName] = [];
400
+ if (this.records[relativeCompilerName][compilerIndex])
401
+ childCompiler.records = this.records[relativeCompilerName][compilerIndex];
402
+ else this.records[relativeCompilerName].push((childCompiler.records = {}));
403
+
404
+ childCompiler.options = Object.create(this.options);
405
+ childCompiler.options.output = Object.create(childCompiler.options.output);
406
+ for (const name in outputOptions) {
407
+ childCompiler.options.output[name] = outputOptions[name];
408
+ }
409
+ childCompiler.parentCompilation = compilation;
410
+
411
+ compilation.hooks.childCompiler.call(
412
+ childCompiler,
413
+ compilerName,
414
+ compilerIndex
415
+ );
416
+
417
+ return childCompiler;
418
+ }
419
+
420
+ isChild() {
421
+ return !!this.parentCompilation;
422
+ }
423
+
424
+ createCompilation() {
425
+ return new Compilation(this);
426
+ }
427
+
428
+ newCompilation(params) {
429
+ const compilation = this.createCompilation();
430
+ compilation.fileTimestamps = this.fileTimestamps;
431
+ compilation.contextTimestamps = this.contextTimestamps;
432
+ compilation.name = this.name;
433
+ compilation.records = this.records;
434
+ compilation.compilationDependencies = params.compilationDependencies;
435
+ this.hooks.thisCompilation.call(compilation, params);
436
+ this.hooks.compilation.call(compilation, params);
437
+ return compilation;
438
+ }
439
+
440
+ createNormalModuleFactory() {
441
+ const normalModuleFactory = new NormalModuleFactory(
442
+ this.options.context,
443
+ this.resolverFactory,
444
+ this.options.module || {}
445
+ );
446
+ this.hooks.normalModuleFactory.call(normalModuleFactory);
447
+ return normalModuleFactory;
448
+ }
449
+
450
+ createContextModuleFactory() {
451
+ const contextModuleFactory = new ContextModuleFactory(this.resolverFactory);
452
+ this.hooks.contextModuleFactory.call(contextModuleFactory);
453
+ return contextModuleFactory;
454
+ }
455
+
456
+ newCompilationParams() {
457
+ const params = {
458
+ normalModuleFactory: this.createNormalModuleFactory(),
459
+ contextModuleFactory: this.createContextModuleFactory(),
460
+ compilationDependencies: new Set()
461
+ };
462
+ return params;
463
+ }
464
+
465
+ compile(callback) {
466
+ const params = this.newCompilationParams();
467
+ this.hooks.beforeCompile.callAsync(params, err => {
468
+ if (err) return callback(err);
469
+
470
+ this.hooks.compile.call(params);
471
+
472
+ const compilation = this.newCompilation(params);
473
+
474
+ this.hooks.make.callAsync(compilation, err => {
475
+ if (err) return callback(err);
476
+
477
+ compilation.finish();
478
+
479
+ compilation.seal(err => {
480
+ if (err) return callback(err);
481
+
482
+ this.hooks.afterCompile.callAsync(compilation, err => {
483
+ if (err) return callback(err);
484
+
485
+ return callback(null, compilation);
486
+ });
487
+ });
488
+ });
489
+ });
490
+ }
491
+ }
492
+
493
+ module.exports = Compiler;