webpack 4.14.0 → 4.16.1
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/LICENSE +20 -20
- package/README.md +5 -2
- package/bin/webpack.js +7 -2
- package/buildin/amd-define.js +3 -3
- package/buildin/amd-options.js +2 -2
- package/buildin/system.js +7 -7
- package/hot/dev-server.js +2 -2
- package/hot/emitter.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 +442 -37
- package/lib/Compiler.js +57 -4
- package/lib/ContextModule.js +23 -16
- package/lib/DefinePlugin.js +49 -0
- 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/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/MemoryOutputFileSystem.js +5 -5
- 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/NullFactory.js +12 -12
- package/lib/OptionsApply.js +10 -10
- package/lib/RuleSet.js +3 -3
- 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/AMDRequireItemDependency.js +22 -22
- package/lib/dependencies/CommonJsRequireDependency.js +22 -22
- package/lib/dependencies/CriticalDependencyWarning.js +20 -20
- package/lib/dependencies/DelegatedSourceDependency.js +18 -18
- package/lib/dependencies/DllEntryDependency.js +20 -20
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +2 -1
- package/lib/dependencies/LoaderDependency.js +3 -0
- package/lib/dependencies/LoaderPlugin.js +21 -2
- package/lib/dependencies/LocalModule.js +23 -23
- package/lib/dependencies/ModuleDependency.js +3 -0
- package/lib/dependencies/ModuleHotAcceptDependency.js +23 -23
- package/lib/dependencies/ModuleHotDeclineDependency.js +23 -23
- package/lib/dependencies/MultiEntryDependency.js +5 -0
- package/lib/dependencies/PrefetchDependency.js +18 -18
- package/lib/dependencies/RequireEnsureItemDependency.js +21 -21
- package/lib/dependencies/RequireResolveDependency.js +22 -22
- 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/NodeOutputFileSystem.js +22 -22
- package/lib/node/NodeSourcePlugin.js +1 -1
- package/lib/optimize/ConcatenatedModule.js +1 -0
- 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 +4 -2
- 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 +1 -1
- 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 +4 -0
- package/lib/webpack.web.js +2 -2
- package/lib/webworker/WebWorkerMainTemplatePlugin.js +1 -1
- package/package.json +27 -17
- package/schemas/WebpackOptions.json +71 -9
- package/schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json +10 -0
- package/schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json +10 -0
package/lib/util/cachedMerge.js
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
const mergeCache = new WeakMap();
|
8
8
|
|
9
9
|
/**
|
10
|
-
* Merges two given objects and caches the result to avoid computation if same objects passed as
|
10
|
+
* Merges two given objects and caches the result to avoid computation if same objects passed as arguments again.
|
11
11
|
* @example
|
12
12
|
* // performs Object.assign(first, second), stores the result in WeakMap and returns result
|
13
13
|
* cachedMerge({a: 1}, {a: 2})
|
package/lib/util/createHash.js
CHANGED
@@ -4,8 +4,18 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
/** @typedef {{new(): Hash}} HashConstructor */
|
8
|
+
/**
|
9
|
+
* @typedef {Object} Hash
|
10
|
+
* @property {function(string|Buffer, string=): Hash} update
|
11
|
+
* @property {function(string): string} digest
|
12
|
+
*/
|
13
|
+
|
7
14
|
const BULK_SIZE = 1000;
|
8
15
|
|
16
|
+
/**
|
17
|
+
* @implements {Hash}
|
18
|
+
*/
|
9
19
|
class BulkUpdateDecorator {
|
10
20
|
constructor(hash) {
|
11
21
|
this.hash = hash;
|
@@ -63,6 +73,11 @@ class DebugHash {
|
|
63
73
|
}
|
64
74
|
}
|
65
75
|
|
76
|
+
/**
|
77
|
+
* Creates a hash by name or function
|
78
|
+
* @param {string | HashConstructor} algorithm the algorithm name or a constructor creating a hash
|
79
|
+
* @returns {Hash} the hash
|
80
|
+
*/
|
66
81
|
module.exports = algorithm => {
|
67
82
|
if (typeof algorithm === "function") {
|
68
83
|
return new BulkUpdateDecorator(new algorithm());
|
@@ -0,0 +1,251 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
// Simulations show these probabilities for a single change
|
4
|
+
// 93.1% that one group is invalidated
|
5
|
+
// 4.8% that two groups are invalidated
|
6
|
+
// 1.1% that 3 groups are invalidated
|
7
|
+
// 0.1% that 4 or more groups are invalidated
|
8
|
+
//
|
9
|
+
// And these for removing/adding 10 lexically adjacent files
|
10
|
+
// 64.5% that one group is invalidated
|
11
|
+
// 24.8% that two groups are invalidated
|
12
|
+
// 7.8% that 3 groups are invalidated
|
13
|
+
// 2.7% that 4 or more groups are invalidated
|
14
|
+
//
|
15
|
+
// And these for removing/adding 3 random files
|
16
|
+
// 0% that one group is invalidated
|
17
|
+
// 3.7% that two groups are invalidated
|
18
|
+
// 80.8% that 3 groups are invalidated
|
19
|
+
// 12.3% that 4 groups are invalidated
|
20
|
+
// 3.2% that 5 or more groups are invalidated
|
21
|
+
|
22
|
+
/**
|
23
|
+
*
|
24
|
+
* @param {string} a key
|
25
|
+
* @param {string} b key
|
26
|
+
* @returns {number} the similarity as number
|
27
|
+
*/
|
28
|
+
const similarity = (a, b) => {
|
29
|
+
const l = Math.min(a.length, b.length);
|
30
|
+
let dist = 0;
|
31
|
+
for (let i = 0; i < l; i++) {
|
32
|
+
const ca = a.charCodeAt(i);
|
33
|
+
const cb = b.charCodeAt(i);
|
34
|
+
dist += Math.max(0, 10 - Math.abs(ca - cb));
|
35
|
+
}
|
36
|
+
return dist;
|
37
|
+
};
|
38
|
+
|
39
|
+
/**
|
40
|
+
* @param {string} a key
|
41
|
+
* @param {string} b key
|
42
|
+
* @returns {string} the common part and a single char for the difference
|
43
|
+
*/
|
44
|
+
const getName = (a, b) => {
|
45
|
+
const l = Math.min(a.length, b.length);
|
46
|
+
let r = "";
|
47
|
+
for (let i = 0; i < l; i++) {
|
48
|
+
const ca = a.charAt(i);
|
49
|
+
const cb = b.charAt(i);
|
50
|
+
r += ca;
|
51
|
+
if (ca === cb) {
|
52
|
+
continue;
|
53
|
+
}
|
54
|
+
return r;
|
55
|
+
}
|
56
|
+
return a;
|
57
|
+
};
|
58
|
+
|
59
|
+
/**
|
60
|
+
* @template T
|
61
|
+
*/
|
62
|
+
class Node {
|
63
|
+
/**
|
64
|
+
* @param {T} item item
|
65
|
+
* @param {string} key key
|
66
|
+
* @param {number} size size
|
67
|
+
*/
|
68
|
+
constructor(item, key, size) {
|
69
|
+
this.item = item;
|
70
|
+
this.key = key;
|
71
|
+
this.size = size;
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* @template T
|
77
|
+
*/
|
78
|
+
class Group {
|
79
|
+
/**
|
80
|
+
* @param {Node<T>[]} nodes nodes
|
81
|
+
* @param {number[]} similarities similarities between the nodes (length = nodes.length - 1)
|
82
|
+
*/
|
83
|
+
constructor(nodes, similarities) {
|
84
|
+
this.nodes = nodes;
|
85
|
+
this.similarities = similarities;
|
86
|
+
this.size = nodes.reduce((size, node) => size + node.size, 0);
|
87
|
+
/** @type {string} */
|
88
|
+
this.key = undefined;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
/**
|
93
|
+
* @template T
|
94
|
+
* @typedef {Object} GroupedItems<T>
|
95
|
+
* @property {string} key
|
96
|
+
* @property {T[]} items
|
97
|
+
* @property {number} size
|
98
|
+
*/
|
99
|
+
|
100
|
+
/**
|
101
|
+
* @template T
|
102
|
+
* @typedef {Object} Options
|
103
|
+
* @property {number} maxSize maximum size of a group
|
104
|
+
* @property {number} minSize minimum size of a group (preferred over maximum size)
|
105
|
+
* @property {Iterable<T>} items a list of items
|
106
|
+
* @property {function(T): number} getSize function to get size of an item
|
107
|
+
* @property {function(T): string} getKey function to get the key of an item
|
108
|
+
*/
|
109
|
+
|
110
|
+
/**
|
111
|
+
* @template T
|
112
|
+
* @param {Options<T>} options options object
|
113
|
+
* @returns {GroupedItems<T>[]} grouped items
|
114
|
+
*/
|
115
|
+
module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
116
|
+
/** @type {Group<T>[]} */
|
117
|
+
const result = [];
|
118
|
+
|
119
|
+
const nodes = Array.from(
|
120
|
+
items,
|
121
|
+
item => new Node(item, getKey(item), getSize(item))
|
122
|
+
);
|
123
|
+
|
124
|
+
/** @type {Node<T>[]} */
|
125
|
+
const initialNodes = [];
|
126
|
+
|
127
|
+
// return nodes bigger than maxSize directly as group
|
128
|
+
for (const node of nodes) {
|
129
|
+
if (node.size >= maxSize) {
|
130
|
+
result.push(new Group([node], []));
|
131
|
+
} else {
|
132
|
+
initialNodes.push(node);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
if (initialNodes.length > 0) {
|
137
|
+
// lexically ordering of keys
|
138
|
+
initialNodes.sort((a, b) => {
|
139
|
+
if (a.key < b.key) return -1;
|
140
|
+
if (a.key > b.key) return 1;
|
141
|
+
return 0;
|
142
|
+
});
|
143
|
+
|
144
|
+
// calculate similarities between lexically adjacent nodes
|
145
|
+
/** @type {number[]} */
|
146
|
+
const similarities = [];
|
147
|
+
for (let i = 1; i < initialNodes.length; i++) {
|
148
|
+
const a = initialNodes[i - 1];
|
149
|
+
const b = initialNodes[i];
|
150
|
+
similarities.push(similarity(a.key, b.key));
|
151
|
+
}
|
152
|
+
|
153
|
+
const queue = [new Group(initialNodes, similarities)];
|
154
|
+
|
155
|
+
while (queue.length) {
|
156
|
+
const group = queue.pop();
|
157
|
+
// only groups bigger than maxSize need to be splitted
|
158
|
+
if (group.size < maxSize) {
|
159
|
+
result.push(group);
|
160
|
+
continue;
|
161
|
+
}
|
162
|
+
|
163
|
+
// find unsplittable area from left and right
|
164
|
+
// going minSize from left and right
|
165
|
+
let left = 0;
|
166
|
+
let leftSize = 0;
|
167
|
+
while (leftSize < minSize) {
|
168
|
+
leftSize += group.nodes[left].size;
|
169
|
+
left++;
|
170
|
+
}
|
171
|
+
let right = group.nodes.length - 1;
|
172
|
+
let rightSize = 0;
|
173
|
+
while (rightSize < minSize) {
|
174
|
+
rightSize += group.nodes[right].size;
|
175
|
+
right--;
|
176
|
+
}
|
177
|
+
|
178
|
+
if (left - 1 > right) {
|
179
|
+
// can't split group while holding minSize
|
180
|
+
// because minSize is preferred of maxSize we return
|
181
|
+
// the group here even while it's too big
|
182
|
+
// To avoid this make sure maxSize > minSize * 3
|
183
|
+
result.push(group);
|
184
|
+
continue;
|
185
|
+
}
|
186
|
+
if (left <= right) {
|
187
|
+
// when there is a area between left and right
|
188
|
+
// we look for best split point
|
189
|
+
// we split at the minimum similarity
|
190
|
+
// here key space is separated the most
|
191
|
+
let best = left - 1;
|
192
|
+
let bestSimilarity = group.similarities[best];
|
193
|
+
for (let i = left; i <= right; i++) {
|
194
|
+
const similarity = group.similarities[i];
|
195
|
+
if (similarity < bestSimilarity) {
|
196
|
+
best = i;
|
197
|
+
bestSimilarity = similarity;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
left = best + 1;
|
201
|
+
right = best;
|
202
|
+
}
|
203
|
+
|
204
|
+
// create two new groups for left and right area
|
205
|
+
// and queue them up
|
206
|
+
const rightNodes = [group.nodes[right + 1]];
|
207
|
+
/** @type {number[]} */
|
208
|
+
const rightSimilaries = [];
|
209
|
+
for (let i = right + 2; i < group.nodes.length; i++) {
|
210
|
+
rightSimilaries.push(group.similarities[i - 1]);
|
211
|
+
rightNodes.push(group.nodes[i]);
|
212
|
+
}
|
213
|
+
queue.push(new Group(rightNodes, rightSimilaries));
|
214
|
+
|
215
|
+
const leftNodes = [group.nodes[0]];
|
216
|
+
/** @type {number[]} */
|
217
|
+
const leftSimilaries = [];
|
218
|
+
for (let i = 1; i < left; i++) {
|
219
|
+
leftSimilaries.push(group.similarities[i - 1]);
|
220
|
+
leftNodes.push(group.nodes[i]);
|
221
|
+
}
|
222
|
+
queue.push(new Group(leftNodes, leftSimilaries));
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
// lexically ordering
|
227
|
+
result.sort((a, b) => {
|
228
|
+
if (a.nodes[0].key < b.nodes[0].key) return -1;
|
229
|
+
if (a.nodes[0].key > b.nodes[0].key) return 1;
|
230
|
+
return 0;
|
231
|
+
});
|
232
|
+
|
233
|
+
// give every group a name
|
234
|
+
for (let i = 0; i < result.length; i++) {
|
235
|
+
const group = result[i];
|
236
|
+
const first = group.nodes[0];
|
237
|
+
const last = group.nodes[group.nodes.length - 1];
|
238
|
+
let name = getName(first.key, last.key);
|
239
|
+
group.key = name;
|
240
|
+
}
|
241
|
+
|
242
|
+
// return the results
|
243
|
+
return result.map(group => {
|
244
|
+
/** @type {GroupedItems} */
|
245
|
+
return {
|
246
|
+
key: group.key,
|
247
|
+
items: group.nodes.map(node => node.item),
|
248
|
+
size: group.size
|
249
|
+
};
|
250
|
+
});
|
251
|
+
};
|
package/lib/util/identifier.js
CHANGED
@@ -74,3 +74,30 @@ exports.makePathsRelative = (context, identifier, cache) => {
|
|
74
74
|
return relativePath;
|
75
75
|
}
|
76
76
|
};
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @param {string} context absolute context path
|
80
|
+
* @param {string} request any request string may containing absolute paths, query string, etc.
|
81
|
+
* @returns {string} a new request string avoiding absolute paths when possible
|
82
|
+
*/
|
83
|
+
exports.contextify = (context, request) => {
|
84
|
+
return request
|
85
|
+
.split("!")
|
86
|
+
.map(r => {
|
87
|
+
const splitPath = r.split("?", 2);
|
88
|
+
if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
89
|
+
splitPath[0] = path.win32.relative(context, splitPath[0]);
|
90
|
+
if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
91
|
+
splitPath[0] = splitPath[0].replace(/\\/g, "/");
|
92
|
+
}
|
93
|
+
}
|
94
|
+
if (/^\//.test(splitPath[0])) {
|
95
|
+
splitPath[0] = path.posix.relative(context, splitPath[0]);
|
96
|
+
}
|
97
|
+
if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
|
98
|
+
splitPath[0] = "./" + splitPath[0];
|
99
|
+
}
|
100
|
+
return splitPath.join("?");
|
101
|
+
})
|
102
|
+
.join("!");
|
103
|
+
};
|
@@ -4,7 +4,7 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
-
const UnsupportedWebAssemblyFeatureError = require("
|
7
|
+
const UnsupportedWebAssemblyFeatureError = require("./UnsupportedWebAssemblyFeatureError");
|
8
8
|
|
9
9
|
class WasmFinalizeExportsPlugin {
|
10
10
|
apply(compiler) {
|
@@ -8,9 +8,10 @@ const Template = require("../Template");
|
|
8
8
|
const WebAssemblyUtils = require("./WebAssemblyUtils");
|
9
9
|
|
10
10
|
/** @typedef {import("../Module")} Module */
|
11
|
+
/** @typedef {import("../MainTemplate")} MainTemplate */
|
11
12
|
|
12
13
|
// Get all wasm modules
|
13
|
-
|
14
|
+
const getAllWasmModules = chunk => {
|
14
15
|
const wasmModules = chunk.getAllAsyncChunks();
|
15
16
|
const array = [];
|
16
17
|
for (const chunk of wasmModules) {
|
@@ -22,7 +23,7 @@ function getAllWasmModules(chunk) {
|
|
22
23
|
}
|
23
24
|
|
24
25
|
return array;
|
25
|
-
}
|
26
|
+
};
|
26
27
|
|
27
28
|
/**
|
28
29
|
* generates the import object function for a module
|
@@ -30,7 +31,7 @@ function getAllWasmModules(chunk) {
|
|
30
31
|
* @param {boolean} mangle mangle imports
|
31
32
|
* @returns {string} source code
|
32
33
|
*/
|
33
|
-
|
34
|
+
const generateImportObject = (module, mangle) => {
|
34
35
|
const waitForInstances = new Map();
|
35
36
|
const properties = [];
|
36
37
|
const usedWasmDependencies = WebAssemblyUtils.getUsedDependencies(
|
@@ -151,7 +152,7 @@ function generateImportObject(module, mangle) {
|
|
151
152
|
"},"
|
152
153
|
]);
|
153
154
|
}
|
154
|
-
}
|
155
|
+
};
|
155
156
|
|
156
157
|
class WasmMainTemplatePlugin {
|
157
158
|
constructor({ generateLoadBinaryCode, supportsStreaming, mangleImports }) {
|
@@ -159,6 +160,11 @@ class WasmMainTemplatePlugin {
|
|
159
160
|
this.supportsStreaming = supportsStreaming;
|
160
161
|
this.mangleImports = mangleImports;
|
161
162
|
}
|
163
|
+
|
164
|
+
/**
|
165
|
+
* @param {MainTemplate} mainTemplate main template
|
166
|
+
* @returns {void}
|
167
|
+
*/
|
162
168
|
apply(mainTemplate) {
|
163
169
|
mainTemplate.hooks.localVars.tap(
|
164
170
|
"WasmMainTemplatePlugin",
|
@@ -32,21 +32,21 @@ const WebAssemblyExportImportedDependency = require("../dependencies/WebAssembly
|
|
32
32
|
* @param {ArrayBuffer} ab - original binary
|
33
33
|
* @returns {ArrayBufferTransform} transform
|
34
34
|
*/
|
35
|
-
|
35
|
+
const preprocess = ab => {
|
36
36
|
const optBin = shrinkPaddedLEB128(new Uint8Array(ab));
|
37
37
|
return optBin.buffer;
|
38
|
-
}
|
38
|
+
};
|
39
39
|
|
40
40
|
/**
|
41
41
|
* @template T
|
42
42
|
* @param {Function[]} fns transforms
|
43
43
|
* @returns {Function} composed transform
|
44
44
|
*/
|
45
|
-
|
45
|
+
const compose = (...fns) => {
|
46
46
|
return fns.reduce((prevFn, nextFn) => {
|
47
47
|
return value => nextFn(prevFn(value));
|
48
48
|
}, value => value);
|
49
|
-
}
|
49
|
+
};
|
50
50
|
|
51
51
|
// TODO replace with @callback
|
52
52
|
|
@@ -70,7 +70,7 @@ const removeStartFunc = state => bin => {
|
|
70
70
|
* @param {Object} ast - Module's AST
|
71
71
|
* @returns {Array<t.ModuleImport>} - nodes
|
72
72
|
*/
|
73
|
-
|
73
|
+
const getImportedGlobals = ast => {
|
74
74
|
const importedGlobals = [];
|
75
75
|
|
76
76
|
t.traverse(ast, {
|
@@ -82,9 +82,9 @@ function getImportedGlobals(ast) {
|
|
82
82
|
});
|
83
83
|
|
84
84
|
return importedGlobals;
|
85
|
-
}
|
85
|
+
};
|
86
86
|
|
87
|
-
|
87
|
+
const getCountImportedFunc = ast => {
|
88
88
|
let count = 0;
|
89
89
|
|
90
90
|
t.traverse(ast, {
|
@@ -96,7 +96,7 @@ function getCountImportedFunc(ast) {
|
|
96
96
|
});
|
97
97
|
|
98
98
|
return count;
|
99
|
-
}
|
99
|
+
};
|
100
100
|
|
101
101
|
/**
|
102
102
|
* Get next type index
|
@@ -104,7 +104,7 @@ function getCountImportedFunc(ast) {
|
|
104
104
|
* @param {Object} ast - Module's AST
|
105
105
|
* @returns {t.Index} - index
|
106
106
|
*/
|
107
|
-
|
107
|
+
const getNextTypeIndex = ast => {
|
108
108
|
const typeSectionMetadata = t.getSectionMetadata(ast, "type");
|
109
109
|
|
110
110
|
if (typeof typeSectionMetadata === "undefined") {
|
@@ -112,7 +112,7 @@ function getNextTypeIndex(ast) {
|
|
112
112
|
}
|
113
113
|
|
114
114
|
return t.indexLiteral(typeSectionMetadata.vectorOfSize.value);
|
115
|
-
}
|
115
|
+
};
|
116
116
|
|
117
117
|
/**
|
118
118
|
* Get next func index
|
@@ -125,7 +125,7 @@ function getNextTypeIndex(ast) {
|
|
125
125
|
* @param {Number} countImportedFunc - number of imported funcs
|
126
126
|
* @returns {t.Index} - index
|
127
127
|
*/
|
128
|
-
|
128
|
+
const getNextFuncIndex = (ast, countImportedFunc) => {
|
129
129
|
const funcSectionMetadata = t.getSectionMetadata(ast, "func");
|
130
130
|
|
131
131
|
if (typeof funcSectionMetadata === "undefined") {
|
@@ -135,7 +135,7 @@ function getNextFuncIndex(ast, countImportedFunc) {
|
|
135
135
|
const vectorOfSize = funcSectionMetadata.vectorOfSize.value;
|
136
136
|
|
137
137
|
return t.indexLiteral(vectorOfSize + countImportedFunc);
|
138
|
-
}
|
138
|
+
};
|
139
139
|
|
140
140
|
/**
|
141
141
|
* Create a init instruction for a global
|
@@ -0,0 +1,88 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
*/
|
4
|
+
"use strict";
|
5
|
+
|
6
|
+
const WebpackError = require("../WebpackError");
|
7
|
+
|
8
|
+
/** @typedef {import("../Module")} Module */
|
9
|
+
/** @typedef {import("../RequestShortener")} RequestShortener */
|
10
|
+
|
11
|
+
/**
|
12
|
+
* @param {Module} module module to get chains from
|
13
|
+
* @param {RequestShortener} requestShortener to make readable identifiers
|
14
|
+
* @returns {string[]} all chains to the module
|
15
|
+
*/
|
16
|
+
const getInitialModuleChains = (module, requestShortener) => {
|
17
|
+
const queue = [
|
18
|
+
{ head: module, message: module.readableIdentifier(requestShortener) }
|
19
|
+
];
|
20
|
+
/** @type {Set<string>} */
|
21
|
+
const results = new Set();
|
22
|
+
/** @type {Set<string>} */
|
23
|
+
const incompleteResults = new Set();
|
24
|
+
/** @type {Set<Module>} */
|
25
|
+
const visitedModules = new Set();
|
26
|
+
|
27
|
+
for (const chain of queue) {
|
28
|
+
const { head, message } = chain;
|
29
|
+
let final = true;
|
30
|
+
/** @type {Set<Module>} */
|
31
|
+
const alreadyReferencedModules = new Set();
|
32
|
+
for (const reason of head.reasons) {
|
33
|
+
const newHead = reason.module;
|
34
|
+
if (newHead) {
|
35
|
+
if (!newHead.getChunks().some(c => c.canBeInitial())) continue;
|
36
|
+
final = false;
|
37
|
+
if (alreadyReferencedModules.has(newHead)) continue;
|
38
|
+
alreadyReferencedModules.add(newHead);
|
39
|
+
const moduleName = newHead.readableIdentifier(requestShortener);
|
40
|
+
const detail = reason.explanation ? ` (${reason.explanation})` : "";
|
41
|
+
const newMessage = `${moduleName}${detail} --> ${message}`;
|
42
|
+
if (visitedModules.has(newHead)) {
|
43
|
+
incompleteResults.add(`... --> ${newMessage}`);
|
44
|
+
continue;
|
45
|
+
}
|
46
|
+
visitedModules.add(newHead);
|
47
|
+
queue.push({
|
48
|
+
head: newHead,
|
49
|
+
message: newMessage
|
50
|
+
});
|
51
|
+
} else {
|
52
|
+
final = false;
|
53
|
+
const newMessage = reason.explanation
|
54
|
+
? `(${reason.explanation}) --> ${message}`
|
55
|
+
: message;
|
56
|
+
results.add(newMessage);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
if (final) {
|
60
|
+
results.add(message);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
for (const result of incompleteResults) {
|
64
|
+
results.add(result);
|
65
|
+
}
|
66
|
+
return Array.from(results);
|
67
|
+
};
|
68
|
+
|
69
|
+
module.exports = class WebAssemblyInInitialChunkError extends WebpackError {
|
70
|
+
/**
|
71
|
+
* @param {Module} module WASM module
|
72
|
+
* @param {RequestShortener} requestShortener request shortener
|
73
|
+
*/
|
74
|
+
constructor(module, requestShortener) {
|
75
|
+
const moduleChains = getInitialModuleChains(module, requestShortener);
|
76
|
+
const message = `WebAssembly module is included in initial chunk.
|
77
|
+
This is not allowed, because WebAssembly download and compilation must happen asynchronous.
|
78
|
+
Add an async splitpoint (i. e. import()) somewhere between your entrypoint and the WebAssembly module:
|
79
|
+
${moduleChains.map(s => `* ${s}`).join("\n")}`;
|
80
|
+
|
81
|
+
super(message);
|
82
|
+
this.name = "WebAssemblyInInitialChunkError";
|
83
|
+
this.hideStack = true;
|
84
|
+
this.module = module;
|
85
|
+
|
86
|
+
Error.captureStackTrace(this, this.constructor);
|
87
|
+
}
|
88
|
+
};
|
@@ -10,12 +10,19 @@ const WebAssemblyGenerator = require("./WebAssemblyGenerator");
|
|
10
10
|
const WebAssemblyJavascriptGenerator = require("./WebAssemblyJavascriptGenerator");
|
11
11
|
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
12
12
|
const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency");
|
13
|
+
const WebAssemblyInInitialChunkError = require("./WebAssemblyInInitialChunkError");
|
14
|
+
|
15
|
+
/** @typedef {import("../Compiler")} Compiler */
|
13
16
|
|
14
17
|
class WebAssemblyModulesPlugin {
|
15
18
|
constructor(options) {
|
16
19
|
this.options = options;
|
17
20
|
}
|
18
21
|
|
22
|
+
/**
|
23
|
+
* @param {Compiler} compiler compiler
|
24
|
+
* @returns {void}
|
25
|
+
*/
|
19
26
|
apply(compiler) {
|
20
27
|
compiler.hooks.compilation.tap(
|
21
28
|
"WebAssemblyModulesPlugin",
|
@@ -78,6 +85,27 @@ class WebAssemblyModulesPlugin {
|
|
78
85
|
return result;
|
79
86
|
}
|
80
87
|
);
|
88
|
+
|
89
|
+
compilation.hooks.afterChunks.tap("WebAssemblyModulesPlugin", () => {
|
90
|
+
const initialWasmModules = new Set();
|
91
|
+
for (const chunk of compilation.chunks) {
|
92
|
+
if (chunk.canBeInitial()) {
|
93
|
+
for (const module of chunk.modulesIterable) {
|
94
|
+
if (module.type.startsWith("webassembly")) {
|
95
|
+
initialWasmModules.add(module);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
for (const module of initialWasmModules) {
|
101
|
+
compilation.errors.push(
|
102
|
+
new WebAssemblyInInitialChunkError(
|
103
|
+
module,
|
104
|
+
compilation.requestShortener
|
105
|
+
)
|
106
|
+
);
|
107
|
+
}
|
108
|
+
});
|
81
109
|
}
|
82
110
|
);
|
83
111
|
}
|
@@ -556,7 +556,7 @@ class JsonpMainTemplatePlugin {
|
|
556
556
|
}
|
557
557
|
);
|
558
558
|
const runtimeSource = Template.getFunctionContent(
|
559
|
-
require("./JsonpMainTemplate.runtime
|
559
|
+
require("./JsonpMainTemplate.runtime")
|
560
560
|
)
|
561
561
|
.replace(/\/\/\$semicolon/g, ";")
|
562
562
|
.replace(/\$require\$/g, mainTemplate.requireFn)
|
@@ -1,18 +1,18 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Tobias Koppers @sokra
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
|
7
|
-
class WebEnvironmentPlugin {
|
8
|
-
constructor(inputFileSystem, outputFileSystem) {
|
9
|
-
this.inputFileSystem = inputFileSystem;
|
10
|
-
this.outputFileSystem = outputFileSystem;
|
11
|
-
}
|
12
|
-
|
13
|
-
apply(compiler) {
|
14
|
-
compiler.outputFileSystem = this.outputFileSystem;
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
module.exports = WebEnvironmentPlugin;
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
class WebEnvironmentPlugin {
|
8
|
+
constructor(inputFileSystem, outputFileSystem) {
|
9
|
+
this.inputFileSystem = inputFileSystem;
|
10
|
+
this.outputFileSystem = outputFileSystem;
|
11
|
+
}
|
12
|
+
|
13
|
+
apply(compiler) {
|
14
|
+
compiler.outputFileSystem = this.outputFileSystem;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
module.exports = WebEnvironmentPlugin;
|
package/lib/webpack.js
CHANGED
@@ -137,6 +137,10 @@ exportPlugins((exports.optimize = {}), {
|
|
137
137
|
ModuleConcatenationPlugin: () =>
|
138
138
|
require("./optimize/ModuleConcatenationPlugin"),
|
139
139
|
OccurrenceOrderPlugin: () => require("./optimize/OccurrenceOrderPlugin"),
|
140
|
+
OccurrenceModuleOrderPlugin: () =>
|
141
|
+
require("./optimize/OccurrenceModuleOrderPlugin"),
|
142
|
+
OccurrenceChunkOrderPlugin: () =>
|
143
|
+
require("./optimize/OccurrenceChunkOrderPlugin"),
|
140
144
|
RuntimeChunkPlugin: () => require("./optimize/RuntimeChunkPlugin"),
|
141
145
|
SideEffectsFlagPlugin: () => require("./optimize/SideEffectsFlagPlugin"),
|
142
146
|
SplitChunksPlugin: () => require("./optimize/SplitChunksPlugin")
|
package/lib/webpack.web.js
CHANGED
@@ -9,7 +9,7 @@ const WebEnvironmentPlugin = require("./web/WebEnvironmentPlugin");
|
|
9
9
|
const WebpackOptionsApply = require("./WebpackOptionsApply");
|
10
10
|
const WebpackOptionsDefaulter = require("./WebpackOptionsDefaulter");
|
11
11
|
|
12
|
-
|
12
|
+
const webpack = (options, callback) => {
|
13
13
|
new WebpackOptionsDefaulter().process(options);
|
14
14
|
|
15
15
|
const compiler = new Compiler();
|
@@ -22,7 +22,7 @@ function webpack(options, callback) {
|
|
22
22
|
compiler.run(callback);
|
23
23
|
}
|
24
24
|
return compiler;
|
25
|
-
}
|
25
|
+
};
|
26
26
|
module.exports = webpack;
|
27
27
|
|
28
28
|
webpack.WebpackOptionsDefaulter = WebpackOptionsDefaulter;
|
@@ -172,7 +172,7 @@ class WebWorkerMainTemplatePlugin {
|
|
172
172
|
)}];\n` +
|
173
173
|
`${globalObject}[${JSON.stringify(hotUpdateFunction)}] = ` +
|
174
174
|
Template.getFunctionContent(
|
175
|
-
require("./WebWorkerMainTemplate.runtime
|
175
|
+
require("./WebWorkerMainTemplate.runtime")
|
176
176
|
)
|
177
177
|
.replace(/\/\/\$semicolon/g, ";")
|
178
178
|
.replace(/\$require\$/g, mainTemplate.requireFn)
|