webpack 4.13.0 → 4.16.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.
- package/bin/webpack.js +7 -2
- package/hot/dev-server.js +2 -2
- package/hot/only-dev-server.js +2 -2
- package/hot/poll.js +5 -2
- package/hot/signal.js +2 -2
- package/lib/AsyncDependenciesBlock.js +44 -0
- package/lib/AutomaticPrefetchPlugin.js +2 -2
- package/lib/Chunk.js +56 -6
- package/lib/ChunkGroup.js +2 -2
- package/lib/ChunkTemplate.js +14 -2
- package/lib/CommentCompilationWarning.js +3 -3
- package/lib/CompatibilityPlugin.js +1 -1
- package/lib/Compilation.js +494 -36
- package/lib/Compiler.js +57 -4
- package/lib/ContextModule.js +23 -16
- package/lib/DelegatedModule.js +9 -1
- package/lib/DelegatedModuleFactoryPlugin.js +7 -1
- package/lib/DependenciesBlock.js +36 -3
- package/lib/DependenciesBlockVariable.js +22 -0
- package/lib/Dependency.js +33 -6
- package/lib/DllEntryPlugin.js +4 -1
- package/lib/DynamicEntryPlugin.js +21 -1
- package/lib/EntryOptionPlugin.js +12 -0
- package/lib/Entrypoint.js +1 -1
- package/lib/EnvironmentPlugin.js +8 -1
- package/lib/ExtendedAPIPlugin.js +8 -4
- package/lib/ExternalModuleFactoryPlugin.js +1 -1
- package/lib/FlagDependencyUsagePlugin.js +18 -13
- package/lib/Generator.js +1 -1
- package/lib/GraphHelpers.js +2 -1
- package/lib/HotModuleReplacement.runtime.js +8 -5
- package/lib/HotModuleReplacementPlugin.js +115 -117
- package/lib/IgnorePlugin.js +1 -1
- package/lib/MainTemplate.js +19 -4
- package/lib/Module.js +9 -3
- package/lib/ModuleReason.js +8 -0
- package/lib/MultiEntryPlugin.js +25 -3
- package/lib/NormalModule.js +5 -23
- package/lib/RuleSet.js +3 -3
- package/lib/RuntimeTemplate.js +4 -0
- package/lib/SingleEntryPlugin.js +20 -1
- package/lib/Stats.js +12 -5
- package/lib/Template.js +4 -1
- package/lib/UmdMainTemplatePlugin.js +12 -12
- package/lib/UseStrictPlugin.js +1 -1
- package/lib/WebpackError.js +4 -0
- package/lib/WebpackOptionsApply.js +92 -10
- package/lib/WebpackOptionsDefaulter.js +23 -6
- package/lib/WebpackOptionsValidationError.js +0 -1
- package/lib/compareLocations.js +13 -17
- package/lib/debug/ProfilingPlugin.js +5 -7
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +4 -6
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +0 -2
- package/lib/dependencies/DependencyReference.js +4 -0
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +18 -8
- package/lib/dependencies/LoaderDependency.js +3 -0
- package/lib/dependencies/LoaderPlugin.js +21 -2
- package/lib/dependencies/ModuleDependency.js +3 -0
- package/lib/dependencies/MultiEntryDependency.js +5 -0
- package/lib/dependencies/SingleEntryDependency.js +3 -0
- package/lib/dependencies/SystemPlugin.js +1 -1
- package/lib/formatLocation.js +55 -41
- package/lib/node/NodeMainTemplateAsync.runtime.js +1 -1
- package/lib/node/NodeMainTemplatePlugin.js +2 -2
- package/lib/node/NodeSourcePlugin.js +1 -1
- package/lib/optimize/ConcatenatedModule.js +24 -8
- package/lib/optimize/ModuleConcatenationPlugin.js +29 -14
- package/lib/optimize/NaturalChunkOrderPlugin.js +41 -0
- package/lib/optimize/OccurrenceChunkOrderPlugin.js +61 -0
- package/lib/optimize/OccurrenceModuleOrderPlugin.js +103 -0
- package/lib/optimize/OccurrenceOrderPlugin.js +2 -0
- package/lib/optimize/SplitChunksPlugin.js +168 -18
- package/lib/util/Semaphore.js +12 -0
- package/lib/util/SetHelpers.js +4 -4
- package/lib/util/SortableSet.js +1 -1
- package/lib/util/cachedMerge.js +1 -1
- package/lib/util/createHash.js +15 -0
- package/lib/util/deterministicGrouping.js +251 -0
- package/lib/util/identifier.js +27 -0
- package/lib/wasm/WasmFinalizeExportsPlugin.js +5 -2
- package/lib/wasm/WasmMainTemplatePlugin.js +10 -4
- package/lib/wasm/WebAssemblyGenerator.js +12 -12
- package/lib/wasm/WebAssemblyInInitialChunkError.js +88 -0
- package/lib/wasm/WebAssemblyModulesPlugin.js +28 -0
- package/lib/web/JsonpMainTemplatePlugin.js +1 -1
- package/lib/web/WebEnvironmentPlugin.js +18 -18
- package/lib/webpack.js +7 -0
- package/lib/webpack.web.js +2 -2
- package/lib/webworker/WebWorkerMainTemplatePlugin.js +1 -1
- package/package.json +21 -11
- package/schemas/WebpackOptions.json +70 -4
- package/schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json +10 -0
- package/schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json +10 -0
@@ -5,6 +5,17 @@
|
|
5
5
|
"use strict";
|
6
6
|
|
7
7
|
const LoaderDependency = require("./LoaderDependency");
|
8
|
+
const NormalModule = require("../NormalModule");
|
9
|
+
|
10
|
+
/** @typedef {import("../Module")} Module */
|
11
|
+
|
12
|
+
/**
|
13
|
+
* @callback LoadModuleCallback
|
14
|
+
* @param {Error=} err error object
|
15
|
+
* @param {string=} source source code
|
16
|
+
* @param {object=} map source map
|
17
|
+
* @param {Module=} module loaded module if successful
|
18
|
+
*/
|
8
19
|
|
9
20
|
class LoaderPlugin {
|
10
21
|
apply(compiler) {
|
@@ -22,9 +33,16 @@ class LoaderPlugin {
|
|
22
33
|
compilation.hooks.normalModuleLoader.tap(
|
23
34
|
"LoaderPlugin",
|
24
35
|
(loaderContext, module) => {
|
36
|
+
/**
|
37
|
+
* @param {string} request the request string to load the module from
|
38
|
+
* @param {LoadModuleCallback} callback callback returning the loaded module or error
|
39
|
+
* @returns {void}
|
40
|
+
*/
|
25
41
|
loaderContext.loadModule = (request, callback) => {
|
26
42
|
const dep = new LoaderDependency(request);
|
27
|
-
dep.loc =
|
43
|
+
dep.loc = {
|
44
|
+
name: request
|
45
|
+
};
|
28
46
|
const factory = compilation.dependencyFactories.get(
|
29
47
|
dep.constructor
|
30
48
|
);
|
@@ -57,7 +75,8 @@ class LoaderPlugin {
|
|
57
75
|
if (!dep.module) {
|
58
76
|
return callback(new Error("Cannot load the module"));
|
59
77
|
}
|
60
|
-
|
78
|
+
// TODO consider removing this in webpack 5
|
79
|
+
if (dep.module instanceof NormalModule && dep.module.error) {
|
61
80
|
return callback(dep.module.error);
|
62
81
|
}
|
63
82
|
if (!dep.module._source) {
|
@@ -3,9 +3,14 @@
|
|
3
3
|
Author Tobias Koppers @sokra
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
|
+
/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */
|
6
7
|
const Dependency = require("../Dependency");
|
7
8
|
|
8
9
|
class MultiEntryDependency extends Dependency {
|
10
|
+
/**
|
11
|
+
* @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies
|
12
|
+
* @param {string} name entry name
|
13
|
+
*/
|
9
14
|
constructor(dependencies, name) {
|
10
15
|
super();
|
11
16
|
this.dependencies = dependencies;
|
@@ -72,7 +72,7 @@ class SystemPlugin {
|
|
72
72
|
parser.hooks.expression.for("System").tap("SystemPlugin", () => {
|
73
73
|
const systemPolyfillRequire = ParserHelpers.requireFileAsExpression(
|
74
74
|
parser.state.module.context,
|
75
|
-
require.resolve("../../buildin/system
|
75
|
+
require.resolve("../../buildin/system")
|
76
76
|
);
|
77
77
|
return ParserHelpers.addParsedVariableToModule(
|
78
78
|
parser,
|
package/lib/formatLocation.js
CHANGED
@@ -5,57 +5,71 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
|
9
|
+
/** @typedef {import("./Dependency").SourcePosition} SourcePosition */
|
10
|
+
|
11
|
+
// TODO webpack 5: pos must be SourcePosition
|
12
|
+
/**
|
13
|
+
* @param {SourcePosition|DependencyLocation|string} pos position
|
14
|
+
* @returns {string} formatted position
|
15
|
+
*/
|
8
16
|
const formatPosition = pos => {
|
9
17
|
if (pos === null) return "";
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
return `${pos}`;
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
return `+${pos.index}`;
|
23
|
-
} else {
|
24
|
-
return "";
|
25
|
-
}
|
26
|
-
default:
|
18
|
+
// TODO webpack 5: Simplify this
|
19
|
+
if (typeof pos === "string") return pos;
|
20
|
+
if (typeof pos === "number") return `${pos}`;
|
21
|
+
if (typeof pos === "object") {
|
22
|
+
if ("line" in pos && "column" in pos) {
|
23
|
+
return `${pos.line}:${pos.column}`;
|
24
|
+
} else if ("line" in pos) {
|
25
|
+
return `${pos.line}:?`;
|
26
|
+
} else if ("index" in pos) {
|
27
|
+
// TODO webpack 5 remove this case
|
28
|
+
return `+${pos.index}`;
|
29
|
+
} else {
|
27
30
|
return "";
|
31
|
+
}
|
28
32
|
}
|
33
|
+
return "";
|
29
34
|
};
|
30
35
|
|
36
|
+
// TODO webpack 5: loc must be DependencyLocation
|
37
|
+
/**
|
38
|
+
* @param {DependencyLocation|SourcePosition|string} loc location
|
39
|
+
* @returns {string} formatted location
|
40
|
+
*/
|
31
41
|
const formatLocation = loc => {
|
32
42
|
if (loc === null) return "";
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
return `${formatPosition(loc.start)}-${formatPosition(loc.end)}`;
|
50
|
-
}
|
51
|
-
}
|
52
|
-
if (loc.start) {
|
53
|
-
return formatPosition(loc.start);
|
43
|
+
// TODO webpack 5: Simplify this
|
44
|
+
if (typeof loc === "string") return loc;
|
45
|
+
if (typeof loc === "number") return `${loc}`;
|
46
|
+
if (typeof loc === "object") {
|
47
|
+
if ("start" in loc && loc.start && "end" in loc && loc.end) {
|
48
|
+
if (
|
49
|
+
typeof loc.start === "object" &&
|
50
|
+
typeof loc.start.line === "number" &&
|
51
|
+
typeof loc.end === "object" &&
|
52
|
+
typeof loc.end.line === "number" &&
|
53
|
+
typeof loc.end.column === "number" &&
|
54
|
+
loc.start.line === loc.end.line
|
55
|
+
) {
|
56
|
+
return `${formatPosition(loc.start)}-${loc.end.column}`;
|
57
|
+
} else {
|
58
|
+
return `${formatPosition(loc.start)}-${formatPosition(loc.end)}`;
|
54
59
|
}
|
55
|
-
|
56
|
-
|
57
|
-
return
|
60
|
+
}
|
61
|
+
if ("start" in loc && loc.start) {
|
62
|
+
return formatPosition(loc.start);
|
63
|
+
}
|
64
|
+
if ("name" in loc && "index" in loc) {
|
65
|
+
return `${loc.name}[${loc.index}]`;
|
66
|
+
}
|
67
|
+
if ("name" in loc) {
|
68
|
+
return loc.name;
|
69
|
+
}
|
70
|
+
return formatPosition(loc);
|
58
71
|
}
|
72
|
+
return "";
|
59
73
|
};
|
60
74
|
|
61
75
|
module.exports = formatLocation;
|
@@ -305,8 +305,8 @@ module.exports = class NodeMainTemplatePlugin {
|
|
305
305
|
);
|
306
306
|
return Template.getFunctionContent(
|
307
307
|
asyncChunkLoading
|
308
|
-
? require("./NodeMainTemplateAsync.runtime
|
309
|
-
: require("./NodeMainTemplate.runtime
|
308
|
+
? require("./NodeMainTemplateAsync.runtime")
|
309
|
+
: require("./NodeMainTemplate.runtime")
|
310
310
|
)
|
311
311
|
.replace(/\$require\$/g, mainTemplate.requireFn)
|
312
312
|
.replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
|
@@ -71,7 +71,7 @@ module.exports = class NodeSourcePlugin {
|
|
71
71
|
.tap("NodeSourcePlugin", () => {
|
72
72
|
const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(
|
73
73
|
parser.state.module.context,
|
74
|
-
require.resolve("../../buildin/global
|
74
|
+
require.resolve("../../buildin/global")
|
75
75
|
);
|
76
76
|
return ParserHelpers.addParsedVariableToModule(
|
77
77
|
parser,
|
@@ -20,6 +20,13 @@ const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibi
|
|
20
20
|
const createHash = require("../util/createHash");
|
21
21
|
|
22
22
|
/** @typedef {import("../Dependency")} Dependency */
|
23
|
+
/** @typedef {import("../Compilation")} Compilation */
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @typedef {Object} ConcatenationEntry
|
27
|
+
* @property {"concatenated" | "external"} type
|
28
|
+
* @property {Module} module
|
29
|
+
*/
|
23
30
|
|
24
31
|
const ensureNsObjSource = (
|
25
32
|
info,
|
@@ -125,6 +132,8 @@ const getFinalName = (
|
|
125
132
|
requestShortener,
|
126
133
|
strictHarmonyModule
|
127
134
|
);
|
135
|
+
} else if (!info.module.isUsed(exportName)) {
|
136
|
+
return "/* unused export */ undefined";
|
128
137
|
}
|
129
138
|
const name = info.internalNames.get(directExport);
|
130
139
|
if (!name) {
|
@@ -275,7 +284,7 @@ const getPathInAst = (ast, node) => {
|
|
275
284
|
};
|
276
285
|
|
277
286
|
class ConcatenatedModule extends Module {
|
278
|
-
constructor(rootModule, modules) {
|
287
|
+
constructor(rootModule, modules, concatenationList) {
|
279
288
|
super("javascript/esm", null);
|
280
289
|
super.setChunks(rootModule._chunks);
|
281
290
|
|
@@ -320,10 +329,9 @@ class ConcatenatedModule extends Module {
|
|
320
329
|
|
321
330
|
this.warnings = [];
|
322
331
|
this.errors = [];
|
323
|
-
this._orderedConcatenationList =
|
324
|
-
|
325
|
-
modulesSet
|
326
|
-
);
|
332
|
+
this._orderedConcatenationList =
|
333
|
+
concatenationList ||
|
334
|
+
ConcatenatedModule.createConcatenationList(rootModule, modulesSet, null);
|
327
335
|
for (const info of this._orderedConcatenationList) {
|
328
336
|
if (info.type === "concatenated") {
|
329
337
|
const m = info.module;
|
@@ -410,7 +418,13 @@ class ConcatenatedModule extends Module {
|
|
410
418
|
}, 0);
|
411
419
|
}
|
412
420
|
|
413
|
-
|
421
|
+
/**
|
422
|
+
* @param {Module} rootModule the root of the concatenation
|
423
|
+
* @param {Set<Module>} modulesSet a set of modules which should be concatenated
|
424
|
+
* @param {Compilation} compilation the compilation context
|
425
|
+
* @returns {ConcatenationEntry[]} concatenation list
|
426
|
+
*/
|
427
|
+
static createConcatenationList(rootModule, modulesSet, compilation) {
|
414
428
|
const list = [];
|
415
429
|
const set = new Set();
|
416
430
|
|
@@ -424,15 +438,16 @@ class ConcatenatedModule extends Module {
|
|
424
438
|
const references = module.dependencies
|
425
439
|
.filter(dep => dep instanceof HarmonyImportDependency)
|
426
440
|
.map(dep => {
|
427
|
-
const ref =
|
441
|
+
const ref = compilation.getDependencyReference(module, dep);
|
428
442
|
if (ref) map.set(ref, dep);
|
429
443
|
return ref;
|
430
444
|
})
|
431
445
|
.filter(ref => ref);
|
432
446
|
DependencyReference.sort(references);
|
447
|
+
// TODO webpack 5: remove this hack, see also DependencyReference
|
433
448
|
return references.map(ref => {
|
434
449
|
const dep = map.get(ref);
|
435
|
-
return () =>
|
450
|
+
return () => compilation.getDependencyReference(module, dep).module;
|
436
451
|
});
|
437
452
|
};
|
438
453
|
|
@@ -624,6 +639,7 @@ class ConcatenatedModule extends Module {
|
|
624
639
|
|
625
640
|
// Must use full identifier in our cache here to ensure that the source
|
626
641
|
// is updated should our dependencies list change.
|
642
|
+
// TODO webpack 5 refactor
|
627
643
|
innerDependencyTemplates.set(
|
628
644
|
"hash",
|
629
645
|
innerDependencyTemplates.get("hash") + this.identifier()
|
@@ -213,8 +213,9 @@ class ModuleConcatenationPlugin {
|
|
213
213
|
const failureCache = new Map();
|
214
214
|
|
215
215
|
// try to add all imports
|
216
|
-
for (const imp of this.
|
217
|
-
const problem = this.
|
216
|
+
for (const imp of this._getImports(compilation, currentRoot)) {
|
217
|
+
const problem = this._tryToAdd(
|
218
|
+
compilation,
|
218
219
|
currentConfiguration,
|
219
220
|
imp,
|
220
221
|
possibleInners,
|
@@ -245,9 +246,15 @@ class ModuleConcatenationPlugin {
|
|
245
246
|
for (const concatConfiguration of concatConfigurations) {
|
246
247
|
if (usedModules.has(concatConfiguration.rootModule)) continue;
|
247
248
|
const modules = concatConfiguration.getModules();
|
249
|
+
const rootModule = concatConfiguration.rootModule;
|
248
250
|
const newModule = new ConcatenatedModule(
|
249
|
-
|
250
|
-
modules
|
251
|
+
rootModule,
|
252
|
+
Array.from(modules),
|
253
|
+
ConcatenatedModule.createConcatenationList(
|
254
|
+
rootModule,
|
255
|
+
modules,
|
256
|
+
compilation
|
257
|
+
)
|
251
258
|
);
|
252
259
|
for (const warning of concatConfiguration.getWarningsSorted()) {
|
253
260
|
newModule.optimizationBailout.push(requestShortener => {
|
@@ -320,15 +327,16 @@ class ModuleConcatenationPlugin {
|
|
320
327
|
);
|
321
328
|
}
|
322
329
|
|
323
|
-
|
330
|
+
_getImports(compilation, module) {
|
324
331
|
return new Set(
|
325
332
|
module.dependencies
|
326
333
|
|
327
334
|
// Get reference info only for harmony Dependencies
|
328
|
-
.map(
|
329
|
-
dep
|
330
|
-
|
331
|
-
|
335
|
+
.map(dep => {
|
336
|
+
if (!(dep instanceof HarmonyImportDependency)) return null;
|
337
|
+
if (!compilation) return dep.getReference();
|
338
|
+
return compilation.getDependencyReference(module, dep);
|
339
|
+
})
|
332
340
|
|
333
341
|
// Reference is valid and has a module
|
334
342
|
// Dependencies are simple enough to concat them
|
@@ -345,7 +353,7 @@ class ModuleConcatenationPlugin {
|
|
345
353
|
);
|
346
354
|
}
|
347
355
|
|
348
|
-
|
356
|
+
_tryToAdd(compilation, config, module, possibleModules, failureCache) {
|
349
357
|
const cacheEntry = failureCache.get(module);
|
350
358
|
if (cacheEntry) {
|
351
359
|
return cacheEntry;
|
@@ -383,7 +391,8 @@ class ModuleConcatenationPlugin {
|
|
383
391
|
)
|
384
392
|
continue;
|
385
393
|
|
386
|
-
const problem = this.
|
394
|
+
const problem = this._tryToAdd(
|
395
|
+
compilation,
|
387
396
|
testConfig,
|
388
397
|
reason.module,
|
389
398
|
possibleModules,
|
@@ -399,8 +408,14 @@ class ModuleConcatenationPlugin {
|
|
399
408
|
config.set(testConfig);
|
400
409
|
|
401
410
|
// Eagerly try to add imports too if possible
|
402
|
-
for (const imp of this.
|
403
|
-
const problem = this.
|
411
|
+
for (const imp of this._getImports(compilation, module)) {
|
412
|
+
const problem = this._tryToAdd(
|
413
|
+
compilation,
|
414
|
+
config,
|
415
|
+
imp,
|
416
|
+
possibleModules,
|
417
|
+
failureCache
|
418
|
+
);
|
404
419
|
if (problem) {
|
405
420
|
config.addWarning(imp, problem);
|
406
421
|
}
|
@@ -451,7 +466,7 @@ class ConcatConfiguration {
|
|
451
466
|
}
|
452
467
|
|
453
468
|
getModules() {
|
454
|
-
return this.modules.
|
469
|
+
return this.modules.asSet();
|
455
470
|
}
|
456
471
|
|
457
472
|
clone() {
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
/** @typedef {import("../Compiler")} Compiler */
|
8
|
+
|
9
|
+
class NaturalChunkOrderPlugin {
|
10
|
+
/**
|
11
|
+
* @param {Compiler} compiler webpack compiler
|
12
|
+
* @returns {void}
|
13
|
+
*/
|
14
|
+
apply(compiler) {
|
15
|
+
compiler.hooks.compilation.tap("NaturalChunkOrderPlugin", compilation => {
|
16
|
+
compilation.hooks.optimizeChunkOrder.tap(
|
17
|
+
"NaturalChunkOrderPlugin",
|
18
|
+
chunks => {
|
19
|
+
chunks.sort((chunkA, chunkB) => {
|
20
|
+
const a = chunkA.modulesIterable[Symbol.iterator]();
|
21
|
+
const b = chunkB.modulesIterable[Symbol.iterator]();
|
22
|
+
// eslint-disable-next-line no-constant-condition
|
23
|
+
while (true) {
|
24
|
+
const aItem = a.next();
|
25
|
+
const bItem = b.next();
|
26
|
+
if (aItem.done && bItem.done) return 0;
|
27
|
+
if (aItem.done) return -1;
|
28
|
+
if (bItem.done) return 1;
|
29
|
+
const aModuleId = aItem.value.id;
|
30
|
+
const bModuleId = bItem.value.id;
|
31
|
+
if (aModuleId < bModuleId) return -1;
|
32
|
+
if (aModuleId > bModuleId) return 1;
|
33
|
+
}
|
34
|
+
});
|
35
|
+
}
|
36
|
+
);
|
37
|
+
});
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
module.exports = NaturalChunkOrderPlugin;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const validateOptions = require("schema-utils");
|
8
|
+
const schema = require("../../schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json");
|
9
|
+
|
10
|
+
class OccurrenceOrderChunkIdsPlugin {
|
11
|
+
constructor(options = {}) {
|
12
|
+
validateOptions(schema, options, "Occurrence Order Chunk Ids Plugin");
|
13
|
+
this.options = options;
|
14
|
+
}
|
15
|
+
|
16
|
+
apply(compiler) {
|
17
|
+
const prioritiseInitial = this.options.prioritiseInitial;
|
18
|
+
compiler.hooks.compilation.tap(
|
19
|
+
"OccurrenceOrderChunkIdsPlugin",
|
20
|
+
compilation => {
|
21
|
+
compilation.hooks.optimizeChunkOrder.tap(
|
22
|
+
"OccurrenceOrderChunkIdsPlugin",
|
23
|
+
chunks => {
|
24
|
+
const occursInInitialChunksMap = new Map();
|
25
|
+
const originalOrder = new Map();
|
26
|
+
|
27
|
+
let i = 0;
|
28
|
+
for (const c of chunks) {
|
29
|
+
let occurs = 0;
|
30
|
+
for (const chunkGroup of c.groupsIterable) {
|
31
|
+
for (const parent of chunkGroup.parentsIterable) {
|
32
|
+
if (parent.isInitial()) occurs++;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
occursInInitialChunksMap.set(c, occurs);
|
36
|
+
originalOrder.set(c, i++);
|
37
|
+
}
|
38
|
+
|
39
|
+
chunks.sort((a, b) => {
|
40
|
+
if (prioritiseInitial) {
|
41
|
+
const aEntryOccurs = occursInInitialChunksMap.get(a);
|
42
|
+
const bEntryOccurs = occursInInitialChunksMap.get(b);
|
43
|
+
if (aEntryOccurs > bEntryOccurs) return -1;
|
44
|
+
if (aEntryOccurs < bEntryOccurs) return 1;
|
45
|
+
}
|
46
|
+
const aOccurs = a.getNumberOfGroups();
|
47
|
+
const bOccurs = b.getNumberOfGroups();
|
48
|
+
if (aOccurs > bOccurs) return -1;
|
49
|
+
if (aOccurs < bOccurs) return 1;
|
50
|
+
const orgA = originalOrder.get(a);
|
51
|
+
const orgB = originalOrder.get(b);
|
52
|
+
return orgB - orgA;
|
53
|
+
});
|
54
|
+
}
|
55
|
+
);
|
56
|
+
}
|
57
|
+
);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
module.exports = OccurrenceOrderChunkIdsPlugin;
|
@@ -0,0 +1,103 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const validateOptions = require("schema-utils");
|
8
|
+
const schema = require("../../schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json");
|
9
|
+
|
10
|
+
class OccurrenceOrderModuleIdsPlugin {
|
11
|
+
constructor(options = {}) {
|
12
|
+
validateOptions(schema, options, "Occurrence Order Module Ids Plugin");
|
13
|
+
this.options = options;
|
14
|
+
}
|
15
|
+
|
16
|
+
apply(compiler) {
|
17
|
+
const prioritiseInitial = this.options.prioritiseInitial;
|
18
|
+
compiler.hooks.compilation.tap(
|
19
|
+
"OccurrenceOrderModuleIdsPlugin",
|
20
|
+
compilation => {
|
21
|
+
compilation.hooks.optimizeModuleOrder.tap(
|
22
|
+
"OccurrenceOrderModuleIdsPlugin",
|
23
|
+
modules => {
|
24
|
+
const occursInInitialChunksMap = new Map();
|
25
|
+
const occursInAllChunksMap = new Map();
|
26
|
+
|
27
|
+
const initialChunkChunkMap = new Map();
|
28
|
+
const entryCountMap = new Map();
|
29
|
+
for (const m of modules) {
|
30
|
+
let initial = 0;
|
31
|
+
let entry = 0;
|
32
|
+
for (const c of m.chunksIterable) {
|
33
|
+
if (c.canBeInitial()) initial++;
|
34
|
+
if (c.entryModule === m) entry++;
|
35
|
+
}
|
36
|
+
initialChunkChunkMap.set(m, initial);
|
37
|
+
entryCountMap.set(m, entry);
|
38
|
+
}
|
39
|
+
|
40
|
+
const countOccursInEntry = (sum, r) => {
|
41
|
+
if (!r.module) {
|
42
|
+
return sum;
|
43
|
+
}
|
44
|
+
return sum + initialChunkChunkMap.get(r.module);
|
45
|
+
};
|
46
|
+
const countOccurs = (sum, r) => {
|
47
|
+
if (!r.module) {
|
48
|
+
return sum;
|
49
|
+
}
|
50
|
+
let factor = 1;
|
51
|
+
if (typeof r.dependency.getNumberOfIdOccurrences === "function") {
|
52
|
+
factor = r.dependency.getNumberOfIdOccurrences();
|
53
|
+
}
|
54
|
+
if (factor === 0) {
|
55
|
+
return sum;
|
56
|
+
}
|
57
|
+
return sum + factor * r.module.getNumberOfChunks();
|
58
|
+
};
|
59
|
+
|
60
|
+
if (prioritiseInitial) {
|
61
|
+
for (const m of modules) {
|
62
|
+
const result =
|
63
|
+
m.reasons.reduce(countOccursInEntry, 0) +
|
64
|
+
initialChunkChunkMap.get(m) +
|
65
|
+
entryCountMap.get(m);
|
66
|
+
occursInInitialChunksMap.set(m, result);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
const originalOrder = new Map();
|
71
|
+
let i = 0;
|
72
|
+
for (const m of modules) {
|
73
|
+
const result =
|
74
|
+
m.reasons.reduce(countOccurs, 0) +
|
75
|
+
m.getNumberOfChunks() +
|
76
|
+
entryCountMap.get(m);
|
77
|
+
occursInAllChunksMap.set(m, result);
|
78
|
+
originalOrder.set(m, i++);
|
79
|
+
}
|
80
|
+
|
81
|
+
modules.sort((a, b) => {
|
82
|
+
if (prioritiseInitial) {
|
83
|
+
const aEntryOccurs = occursInInitialChunksMap.get(a);
|
84
|
+
const bEntryOccurs = occursInInitialChunksMap.get(b);
|
85
|
+
if (aEntryOccurs > bEntryOccurs) return -1;
|
86
|
+
if (aEntryOccurs < bEntryOccurs) return 1;
|
87
|
+
}
|
88
|
+
const aOccurs = occursInAllChunksMap.get(a);
|
89
|
+
const bOccurs = occursInAllChunksMap.get(b);
|
90
|
+
if (aOccurs > bOccurs) return -1;
|
91
|
+
if (aOccurs < bOccurs) return 1;
|
92
|
+
const orgA = originalOrder.get(a);
|
93
|
+
const orgB = originalOrder.get(b);
|
94
|
+
return orgB - orgA;
|
95
|
+
});
|
96
|
+
}
|
97
|
+
);
|
98
|
+
}
|
99
|
+
);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
module.exports = OccurrenceOrderModuleIdsPlugin;
|