webpack 5.14.0 → 5.18.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.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/bin/webpack.js +0 -0
- package/hot/lazy-compilation-node.js +38 -0
- package/hot/lazy-compilation-web.js +74 -0
- package/lib/AutomaticPrefetchPlugin.js +14 -7
- package/lib/CacheFacade.js +1 -0
- package/lib/ChunkGraph.js +132 -19
- package/lib/CodeGenerationResults.js +43 -8
- package/lib/Compilation.js +253 -149
- package/lib/Compiler.js +7 -2
- package/lib/ContextModule.js +2 -2
- package/lib/Dependency.js +1 -7
- package/lib/ExportsInfo.js +23 -5
- package/lib/ExternalModuleFactoryPlugin.js +46 -3
- package/lib/FileSystemInfo.js +192 -137
- package/lib/HotModuleReplacementPlugin.js +76 -29
- package/lib/IgnoreErrorModuleFactory.js +39 -0
- package/lib/Module.js +2 -3
- package/lib/NormalModuleFactory.js +27 -8
- package/lib/Template.js +32 -23
- package/lib/WebpackIsIncludedPlugin.js +85 -0
- package/lib/WebpackOptionsApply.js +27 -5
- package/lib/cache/PackFileCacheStrategy.js +5 -1
- package/lib/config/defaults.js +18 -18
- package/lib/config/normalization.js +44 -9
- package/lib/debug/ProfilingPlugin.js +20 -1
- package/lib/dependencies/AMDDefineDependency.js +1 -1
- package/lib/dependencies/AMDPlugin.js +6 -7
- package/lib/dependencies/CommonJsImportsParserPlugin.js +43 -1
- package/lib/dependencies/CommonJsPlugin.js +1 -6
- package/lib/dependencies/ContextDependencyHelpers.js +3 -2
- package/lib/dependencies/ExportsInfoDependency.js +0 -20
- package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +1 -2
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +0 -29
- package/lib/dependencies/HarmonyImportDependency.js +0 -41
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +2 -3
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -36
- package/lib/dependencies/HarmonyModulesPlugin.js +2 -2
- package/lib/dependencies/ImportPlugin.js +1 -6
- package/lib/dependencies/JsonExportsDependency.js +0 -1
- package/lib/dependencies/ModuleDecoratorDependency.js +0 -1
- package/lib/dependencies/NullDependency.js +0 -8
- package/lib/dependencies/ProvidedDependency.js +0 -1
- package/lib/dependencies/StaticExportsDependency.js +0 -12
- package/lib/dependencies/SystemPlugin.js +0 -4
- package/lib/dependencies/URLDependency.js +45 -3
- package/lib/dependencies/URLPlugin.js +33 -7
- package/lib/dependencies/WebpackIsIncludedDependency.js +80 -0
- package/lib/hmr/LazyCompilationPlugin.js +348 -0
- package/lib/hmr/lazyCompilationBackend.js +86 -0
- package/lib/javascript/JavascriptModulesPlugin.js +4 -3
- package/lib/javascript/JavascriptParser.js +20 -5
- package/lib/library/AssignLibraryPlugin.js +13 -4
- package/lib/library/EnableLibraryPlugin.js +12 -0
- package/lib/optimize/ConcatenatedModule.js +0 -12
- package/lib/optimize/InnerGraph.js +32 -0
- package/lib/optimize/SplitChunksPlugin.js +4 -1
- package/lib/serialization/ObjectMiddleware.js +7 -5
- package/lib/sharing/ProvideSharedModule.js +1 -1
- package/lib/sharing/ShareRuntimeModule.js +2 -2
- package/lib/stats/DefaultStatsPresetPlugin.js +1 -0
- package/lib/util/MapHelpers.js +22 -0
- package/lib/util/binarySearchBounds.js +86 -0
- package/lib/util/createHash.js +13 -7
- package/lib/util/internalSerializables.js +2 -0
- package/lib/util/processAsyncTree.js +61 -0
- package/lib/util/runtime.js +12 -1
- package/package.json +3 -3
- package/schemas/WebpackOptions.json +330 -140
- package/schemas/plugins/container/ContainerPlugin.json +2 -1
- package/schemas/plugins/container/ModuleFederationPlugin.json +2 -1
- package/types.d.ts +320 -121
@@ -0,0 +1,80 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Ivan Kopeykin @vankop
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
const Dependency = require("../Dependency");
|
9
|
+
const Template = require("../Template");
|
10
|
+
const makeSerializable = require("../util/makeSerializable");
|
11
|
+
const ModuleDependency = require("./ModuleDependency");
|
12
|
+
|
13
|
+
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
|
14
|
+
/** @typedef {import("../Compilation")} Compilation */
|
15
|
+
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
|
16
|
+
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
|
17
|
+
/** @typedef {import("../ModuleGraph")} ModuleGraph */
|
18
|
+
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
|
19
|
+
|
20
|
+
class WebpackIsIncludedDependency extends ModuleDependency {
|
21
|
+
constructor(request, range) {
|
22
|
+
super(request);
|
23
|
+
|
24
|
+
this.weak = true;
|
25
|
+
this.range = range;
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Returns list of exports referenced by this dependency
|
30
|
+
* @param {ModuleGraph} moduleGraph module graph
|
31
|
+
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
|
32
|
+
* @returns {(string[] | ReferencedExport)[]} referenced exports
|
33
|
+
*/
|
34
|
+
getReferencedExports(moduleGraph, runtime) {
|
35
|
+
// This doesn't use any export
|
36
|
+
return Dependency.NO_EXPORTS_REFERENCED;
|
37
|
+
}
|
38
|
+
|
39
|
+
get type() {
|
40
|
+
return "__webpack_is_included__";
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
makeSerializable(
|
45
|
+
WebpackIsIncludedDependency,
|
46
|
+
"webpack/lib/dependencies/WebpackIsIncludedDependency"
|
47
|
+
);
|
48
|
+
|
49
|
+
WebpackIsIncludedDependency.Template = class WebpackIsIncludedDependencyTemplate extends (
|
50
|
+
ModuleDependency.Template
|
51
|
+
) {
|
52
|
+
/**
|
53
|
+
* @param {Dependency} dependency the dependency for which the template should be applied
|
54
|
+
* @param {ReplaceSource} source the current replace source which can be modified
|
55
|
+
* @param {DependencyTemplateContext} templateContext the context object
|
56
|
+
* @returns {void}
|
57
|
+
*/
|
58
|
+
apply(dependency, source, { runtimeTemplate, chunkGraph, moduleGraph }) {
|
59
|
+
const dep = /** @type {WebpackIsIncludedDependency} */ (dependency);
|
60
|
+
const connection = moduleGraph.getConnection(dep);
|
61
|
+
const included = connection
|
62
|
+
? chunkGraph.getNumberOfModuleChunks(connection.module) > 0
|
63
|
+
: false;
|
64
|
+
const comment = runtimeTemplate.outputOptions.pathinfo
|
65
|
+
? Template.toComment(
|
66
|
+
`__webpack_is_included__ ${runtimeTemplate.requestShortener.shorten(
|
67
|
+
dep.request
|
68
|
+
)}`
|
69
|
+
)
|
70
|
+
: "";
|
71
|
+
|
72
|
+
source.replace(
|
73
|
+
dep.range[0],
|
74
|
+
dep.range[1] - 1,
|
75
|
+
`${comment}${JSON.stringify(included)}`
|
76
|
+
);
|
77
|
+
}
|
78
|
+
};
|
79
|
+
|
80
|
+
module.exports = WebpackIsIncludedDependency;
|
@@ -0,0 +1,348 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
const { RawSource } = require("webpack-sources");
|
9
|
+
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
|
10
|
+
const Dependency = require("../Dependency");
|
11
|
+
const Module = require("../Module");
|
12
|
+
const ModuleFactory = require("../ModuleFactory");
|
13
|
+
const RuntimeGlobals = require("../RuntimeGlobals");
|
14
|
+
const Template = require("../Template");
|
15
|
+
const CommonJsRequireDependency = require("../dependencies/CommonJsRequireDependency");
|
16
|
+
const { registerNotSerializable } = require("../util/serialization");
|
17
|
+
|
18
|
+
/** @typedef {import("../../declarations/WebpackOptions")} WebpackOptions */
|
19
|
+
/** @typedef {import("../Compilation")} Compilation */
|
20
|
+
/** @typedef {import("../Compiler")} Compiler */
|
21
|
+
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
|
22
|
+
/** @typedef {import("../Module").BuildMeta} BuildMeta */
|
23
|
+
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
|
24
|
+
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
|
25
|
+
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
|
26
|
+
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
|
27
|
+
/** @typedef {import("../ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
|
28
|
+
/** @typedef {import("../ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
29
|
+
/** @typedef {import("../RequestShortener")} RequestShortener */
|
30
|
+
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
|
31
|
+
/** @typedef {import("../WebpackError")} WebpackError */
|
32
|
+
/** @typedef {import("../util/Hash")} Hash */
|
33
|
+
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
|
34
|
+
|
35
|
+
const TYPES = new Set(["javascript"]);
|
36
|
+
|
37
|
+
class LazyCompilationDependency extends Dependency {
|
38
|
+
constructor(originalModule) {
|
39
|
+
super();
|
40
|
+
this.originalModule = originalModule;
|
41
|
+
}
|
42
|
+
|
43
|
+
get category() {
|
44
|
+
return "esm";
|
45
|
+
}
|
46
|
+
|
47
|
+
get type() {
|
48
|
+
return "lazy import()";
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* @returns {string | null} an identifier to merge equal requests
|
53
|
+
*/
|
54
|
+
getResourceIdentifier() {
|
55
|
+
return this.originalModule.identifier();
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
registerNotSerializable(LazyCompilationDependency);
|
60
|
+
|
61
|
+
class LazyCompilationProxyModule extends Module {
|
62
|
+
constructor(context, originalModule, request, client, data, active) {
|
63
|
+
super("lazy-compilation-proxy", context, originalModule.layer);
|
64
|
+
this.originalModule = originalModule;
|
65
|
+
this.request = request;
|
66
|
+
this.client = client;
|
67
|
+
this.data = data;
|
68
|
+
this.active = active;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* @returns {string} a unique identifier of the module
|
73
|
+
*/
|
74
|
+
identifier() {
|
75
|
+
return `lazy-compilation-proxy|${this.originalModule.identifier()}`;
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @param {RequestShortener} requestShortener the request shortener
|
80
|
+
* @returns {string} a user readable identifier of the module
|
81
|
+
*/
|
82
|
+
readableIdentifier(requestShortener) {
|
83
|
+
return `lazy-compilation-proxy ${this.originalModule.readableIdentifier(
|
84
|
+
requestShortener
|
85
|
+
)}`;
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Assuming this module is in the cache. Update the (cached) module with
|
90
|
+
* the fresh module from the factory. Usually updates internal references
|
91
|
+
* and properties.
|
92
|
+
* @param {Module} module fresh module
|
93
|
+
* @returns {void}
|
94
|
+
*/
|
95
|
+
updateCacheModule(module) {
|
96
|
+
super.updateCacheModule(module);
|
97
|
+
const m = /** @type {LazyCompilationProxyModule} */ (module);
|
98
|
+
this.active = m.active;
|
99
|
+
}
|
100
|
+
|
101
|
+
/**
|
102
|
+
* @param {LibIdentOptions} options options
|
103
|
+
* @returns {string | null} an identifier for library inclusion
|
104
|
+
*/
|
105
|
+
libIdent(options) {
|
106
|
+
return `${this.originalModule.libIdent(options)}!lazy-compilation-proxy`;
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* @param {NeedBuildContext} context context info
|
111
|
+
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
112
|
+
* @returns {void}
|
113
|
+
*/
|
114
|
+
needBuild(context, callback) {
|
115
|
+
callback(null, !this.buildInfo || this.buildInfo.active !== this.active);
|
116
|
+
}
|
117
|
+
|
118
|
+
/**
|
119
|
+
* @param {WebpackOptions} options webpack options
|
120
|
+
* @param {Compilation} compilation the compilation
|
121
|
+
* @param {ResolverWithOptions} resolver the resolver
|
122
|
+
* @param {InputFileSystem} fs the file system
|
123
|
+
* @param {function(WebpackError=): void} callback callback function
|
124
|
+
* @returns {void}
|
125
|
+
*/
|
126
|
+
build(options, compilation, resolver, fs, callback) {
|
127
|
+
this.buildInfo = {
|
128
|
+
active: this.active
|
129
|
+
};
|
130
|
+
/** @type {BuildMeta} */
|
131
|
+
this.buildMeta = {};
|
132
|
+
this.clearDependenciesAndBlocks();
|
133
|
+
const dep = new CommonJsRequireDependency(this.client);
|
134
|
+
this.addDependency(dep);
|
135
|
+
if (this.active) {
|
136
|
+
const dep = new LazyCompilationDependency(this.originalModule);
|
137
|
+
const block = new AsyncDependenciesBlock({});
|
138
|
+
block.addDependency(dep);
|
139
|
+
this.addBlock(block);
|
140
|
+
}
|
141
|
+
callback();
|
142
|
+
}
|
143
|
+
|
144
|
+
/**
|
145
|
+
* @returns {Set<string>} types available (do not mutate)
|
146
|
+
*/
|
147
|
+
getSourceTypes() {
|
148
|
+
return TYPES;
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* @param {string=} type the source type for which the size should be estimated
|
153
|
+
* @returns {number} the estimated size of the module (must be non-zero)
|
154
|
+
*/
|
155
|
+
size(type) {
|
156
|
+
return 200;
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* @param {CodeGenerationContext} context context for code generation
|
161
|
+
* @returns {CodeGenerationResult} result
|
162
|
+
*/
|
163
|
+
codeGeneration({ runtimeTemplate, chunkGraph, moduleGraph }) {
|
164
|
+
const sources = new Map();
|
165
|
+
const runtimeRequirements = new Set();
|
166
|
+
runtimeRequirements.add(RuntimeGlobals.module);
|
167
|
+
const clientDep = /** @type {CommonJsRequireDependency} */ (this
|
168
|
+
.dependencies[0]);
|
169
|
+
const clientModule = moduleGraph.getModule(clientDep);
|
170
|
+
const block = this.blocks[0];
|
171
|
+
const client = Template.asString([
|
172
|
+
`var client = ${runtimeTemplate.moduleExports({
|
173
|
+
module: clientModule,
|
174
|
+
chunkGraph,
|
175
|
+
request: clientDep.userRequest,
|
176
|
+
runtimeRequirements
|
177
|
+
})}`,
|
178
|
+
`var data = ${JSON.stringify(this.data)};`
|
179
|
+
]);
|
180
|
+
const keepActive = Template.asString([
|
181
|
+
`var dispose = client.keepAlive({ data, active: ${JSON.stringify(
|
182
|
+
!!block
|
183
|
+
)}, module, onError });`
|
184
|
+
]);
|
185
|
+
let source;
|
186
|
+
if (block) {
|
187
|
+
const dep = block.dependencies[0];
|
188
|
+
const module = moduleGraph.getModule(dep);
|
189
|
+
source = Template.asString([
|
190
|
+
client,
|
191
|
+
`module.exports = ${runtimeTemplate.moduleNamespacePromise({
|
192
|
+
chunkGraph,
|
193
|
+
block,
|
194
|
+
module,
|
195
|
+
request: this.request,
|
196
|
+
strict: false, // TODO this should be inherited from the original module
|
197
|
+
message: "import()",
|
198
|
+
runtimeRequirements
|
199
|
+
})};`,
|
200
|
+
"if (module.hot) {",
|
201
|
+
Template.indent([
|
202
|
+
"module.hot.accept();",
|
203
|
+
`module.hot.accept(${JSON.stringify(
|
204
|
+
chunkGraph.getModuleId(module)
|
205
|
+
)}, function() { module.hot.invalidate(); });`,
|
206
|
+
"module.hot.dispose(function(data) { delete data.resolveSelf; dispose(data); });",
|
207
|
+
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);"
|
208
|
+
]),
|
209
|
+
"}",
|
210
|
+
"function onError() { /* ignore */ }",
|
211
|
+
keepActive
|
212
|
+
]);
|
213
|
+
} else {
|
214
|
+
source = Template.asString([
|
215
|
+
client,
|
216
|
+
"var resolveSelf, onError;",
|
217
|
+
`module.exports = new Promise(function(resolve, reject) { resolveSelf = resolve; onError = reject; });`,
|
218
|
+
"if (module.hot) {",
|
219
|
+
Template.indent([
|
220
|
+
"module.hot.accept();",
|
221
|
+
"if (module.hot.data && module.hot.data.resolveSelf) module.hot.data.resolveSelf(module.exports);",
|
222
|
+
"module.hot.dispose(function(data) { data.resolveSelf = resolveSelf; dispose(data); });"
|
223
|
+
]),
|
224
|
+
"}",
|
225
|
+
keepActive
|
226
|
+
]);
|
227
|
+
}
|
228
|
+
sources.set("javascript", new RawSource(source));
|
229
|
+
return {
|
230
|
+
sources,
|
231
|
+
runtimeRequirements
|
232
|
+
};
|
233
|
+
}
|
234
|
+
|
235
|
+
/**
|
236
|
+
* @param {Hash} hash the hash used to track dependencies
|
237
|
+
* @param {UpdateHashContext} context context
|
238
|
+
* @returns {void}
|
239
|
+
*/
|
240
|
+
updateHash(hash, context) {
|
241
|
+
super.updateHash(hash, context);
|
242
|
+
hash.update(this.active ? "active" : "");
|
243
|
+
hash.update(JSON.stringify(this.data));
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
registerNotSerializable(LazyCompilationProxyModule);
|
248
|
+
|
249
|
+
class LazyCompilationDependencyFactory extends ModuleFactory {
|
250
|
+
constructor(factory) {
|
251
|
+
super();
|
252
|
+
this._factory = factory;
|
253
|
+
}
|
254
|
+
|
255
|
+
/**
|
256
|
+
* @param {ModuleFactoryCreateData} data data object
|
257
|
+
* @param {function(Error=, ModuleFactoryResult=): void} callback callback
|
258
|
+
* @returns {void}
|
259
|
+
*/
|
260
|
+
create(data, callback) {
|
261
|
+
const dependency = /** @type {LazyCompilationDependency} */ (data
|
262
|
+
.dependencies[0]);
|
263
|
+
callback(null, {
|
264
|
+
module: dependency.originalModule
|
265
|
+
});
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
class LazyCompilationPlugin {
|
270
|
+
/**
|
271
|
+
* @param {Object} options options
|
272
|
+
* @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend
|
273
|
+
* @param {string} options.client the client reference
|
274
|
+
* @param {boolean} options.entries true, when entries are lazy compiled
|
275
|
+
*/
|
276
|
+
constructor({ backend, client, entries }) {
|
277
|
+
this.backend = backend;
|
278
|
+
this.client = client;
|
279
|
+
this.entries = entries;
|
280
|
+
}
|
281
|
+
/**
|
282
|
+
* Apply the plugin
|
283
|
+
* @param {Compiler} compiler the compiler instance
|
284
|
+
* @returns {void}
|
285
|
+
*/
|
286
|
+
apply(compiler) {
|
287
|
+
let backend;
|
288
|
+
compiler.hooks.beforeCompile.tapAsync(
|
289
|
+
"LazyCompilationPlugin",
|
290
|
+
(params, callback) => {
|
291
|
+
if (backend !== undefined) return callback();
|
292
|
+
const promise = this.backend(compiler, this.client, (err, result) => {
|
293
|
+
if (err) return callback(err);
|
294
|
+
backend = result;
|
295
|
+
callback();
|
296
|
+
});
|
297
|
+
if (promise && promise.then) {
|
298
|
+
promise.then(b => {
|
299
|
+
backend = b;
|
300
|
+
callback();
|
301
|
+
}, callback);
|
302
|
+
}
|
303
|
+
}
|
304
|
+
);
|
305
|
+
compiler.hooks.thisCompilation.tap(
|
306
|
+
"LazyCompilationPlugin",
|
307
|
+
(compilation, { normalModuleFactory }) => {
|
308
|
+
normalModuleFactory.hooks.module.tap(
|
309
|
+
"LazyCompilationPlugin",
|
310
|
+
(originalModule, createData, resolveData) => {
|
311
|
+
if (
|
312
|
+
resolveData.dependencies.every(
|
313
|
+
dep =>
|
314
|
+
dep.type === "import()" ||
|
315
|
+
(this.entries && dep.type === "entry")
|
316
|
+
) &&
|
317
|
+
!/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test(
|
318
|
+
resolveData.request
|
319
|
+
)
|
320
|
+
) {
|
321
|
+
const moduleInfo = backend.module(originalModule);
|
322
|
+
if (!moduleInfo) return;
|
323
|
+
const { client, data, active } = moduleInfo;
|
324
|
+
|
325
|
+
return new LazyCompilationProxyModule(
|
326
|
+
compiler.context,
|
327
|
+
originalModule,
|
328
|
+
resolveData.request,
|
329
|
+
client,
|
330
|
+
data,
|
331
|
+
active
|
332
|
+
);
|
333
|
+
}
|
334
|
+
}
|
335
|
+
);
|
336
|
+
compilation.dependencyFactories.set(
|
337
|
+
LazyCompilationDependency,
|
338
|
+
new LazyCompilationDependencyFactory()
|
339
|
+
);
|
340
|
+
}
|
341
|
+
);
|
342
|
+
compiler.hooks.shutdown.tapAsync("LazyCompilationPlugin", callback => {
|
343
|
+
backend.dispose(callback);
|
344
|
+
});
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
module.exports = LazyCompilationPlugin;
|
@@ -0,0 +1,86 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
const http = require("http");
|
9
|
+
|
10
|
+
/** @typedef {import("../Compiler")} Compiler */
|
11
|
+
|
12
|
+
/**
|
13
|
+
* @param {Compiler} compiler compiler
|
14
|
+
* @param {string} client client reference
|
15
|
+
* @param {function(Error?, any?): void} callback callback
|
16
|
+
* @returns {void}
|
17
|
+
*/
|
18
|
+
module.exports = (compiler, client, callback) => {
|
19
|
+
const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
|
20
|
+
const activeModules = new Map();
|
21
|
+
const prefix = "/lazy-compilation-using-";
|
22
|
+
const server = http.createServer((req, res) => {
|
23
|
+
const keys = req.url.slice(prefix.length).split("@");
|
24
|
+
req.socket.on("close", () => {
|
25
|
+
setTimeout(() => {
|
26
|
+
for (const key of keys) {
|
27
|
+
const oldValue = activeModules.get(key) || 0;
|
28
|
+
activeModules.set(key, oldValue - 1);
|
29
|
+
if (oldValue === 1) {
|
30
|
+
logger.log(
|
31
|
+
`${key} is no longer in use. Next compilation will skip this module.`
|
32
|
+
);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}, 120000);
|
36
|
+
});
|
37
|
+
req.socket.setNoDelay(true);
|
38
|
+
res.writeHead(200, {
|
39
|
+
"content-type": "text/event-stream",
|
40
|
+
"Access-Control-Allow-Origin": "*"
|
41
|
+
});
|
42
|
+
res.write("\n");
|
43
|
+
let moduleActivated = false;
|
44
|
+
for (const key of keys) {
|
45
|
+
const oldValue = activeModules.get(key) || 0;
|
46
|
+
activeModules.set(key, oldValue + 1);
|
47
|
+
if (oldValue === 0) {
|
48
|
+
logger.log(`${key} is now in use and will be compiled.`);
|
49
|
+
moduleActivated = true;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
if (moduleActivated && compiler.watching) compiler.watching.invalidate();
|
53
|
+
});
|
54
|
+
server.listen(err => {
|
55
|
+
if (err) return callback(err);
|
56
|
+
const addr = server.address();
|
57
|
+
if (typeof addr === "string") throw new Error("addr must not be a string");
|
58
|
+
const urlBase =
|
59
|
+
addr.address === "::" || addr.address === "0.0.0.0"
|
60
|
+
? `http://localhost:${addr.port}`
|
61
|
+
: addr.family === "IPv6"
|
62
|
+
? `http://[${addr.address}]:${addr.port}`
|
63
|
+
: `http://${addr.address}:${addr.port}`;
|
64
|
+
logger.log(
|
65
|
+
`Server-Sent-Events server for lazy compilation open at ${urlBase}.`
|
66
|
+
);
|
67
|
+
callback(null, {
|
68
|
+
dispose(callback) {
|
69
|
+
server.close(callback);
|
70
|
+
},
|
71
|
+
module(originalModule) {
|
72
|
+
const key = `${encodeURIComponent(
|
73
|
+
originalModule.identifier().replace(/\\/g, "/").replace(/@/g, "_")
|
74
|
+
).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
|
75
|
+
const active = activeModules.get(key) > 0;
|
76
|
+
return {
|
77
|
+
client: `webpack/hot/lazy-compilation-${
|
78
|
+
compiler.options.externalsPresets.node ? "node" : "web"
|
79
|
+
}.js?${encodeURIComponent(urlBase + prefix)}`,
|
80
|
+
data: key,
|
81
|
+
active
|
82
|
+
};
|
83
|
+
}
|
84
|
+
});
|
85
|
+
});
|
86
|
+
};
|
@@ -848,6 +848,7 @@ class JavascriptModulesPlugin {
|
|
848
848
|
buf.push("");
|
849
849
|
}
|
850
850
|
|
851
|
+
const maybeReturn = returnExportsFromRuntime ? "return " : "";
|
851
852
|
if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
|
852
853
|
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
853
854
|
/** @type {string[]} */
|
@@ -933,7 +934,7 @@ class JavascriptModulesPlugin {
|
|
933
934
|
);
|
934
935
|
buf.push("");
|
935
936
|
startup.push("// run startup");
|
936
|
-
startup.push(
|
937
|
+
startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
|
937
938
|
} else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
|
938
939
|
buf.push("// the startup function");
|
939
940
|
buf.push(
|
@@ -951,7 +952,7 @@ class JavascriptModulesPlugin {
|
|
951
952
|
startup.push("// startup");
|
952
953
|
startup.push(Template.asString(buf2));
|
953
954
|
afterStartup.push("// run runtime startup");
|
954
|
-
afterStartup.push(
|
955
|
+
afterStartup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
|
955
956
|
} else {
|
956
957
|
startup.push("// startup");
|
957
958
|
startup.push(Template.asString(buf2));
|
@@ -980,7 +981,7 @@ class JavascriptModulesPlugin {
|
|
980
981
|
`${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()}`
|
981
982
|
);
|
982
983
|
startup.push("// run startup");
|
983
|
-
startup.push(
|
984
|
+
startup.push(`${maybeReturn}${RuntimeGlobals.startup}();`);
|
984
985
|
}
|
985
986
|
return result;
|
986
987
|
}
|
@@ -10,6 +10,7 @@ const { SyncBailHook, HookMap } = require("tapable");
|
|
10
10
|
const vm = require("vm");
|
11
11
|
const Parser = require("../Parser");
|
12
12
|
const StackedMap = require("../util/StackedMap");
|
13
|
+
const binarySearchBounds = require("../util/binarySearchBounds");
|
13
14
|
const memoize = require("../util/memoize");
|
14
15
|
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
|
15
16
|
|
@@ -2625,13 +2626,17 @@ class JavascriptParser extends Parser {
|
|
2625
2626
|
}
|
2626
2627
|
|
2627
2628
|
walkCallExpression(expression) {
|
2629
|
+
const isSimpleFunction = fn => {
|
2630
|
+
return fn.params.every(p => p.type === "Identifier");
|
2631
|
+
};
|
2628
2632
|
if (
|
2629
2633
|
expression.callee.type === "MemberExpression" &&
|
2630
2634
|
expression.callee.object.type.endsWith("FunctionExpression") &&
|
2631
2635
|
!expression.callee.computed &&
|
2632
2636
|
(expression.callee.property.name === "call" ||
|
2633
2637
|
expression.callee.property.name === "bind") &&
|
2634
|
-
expression.arguments.length > 0
|
2638
|
+
expression.arguments.length > 0 &&
|
2639
|
+
isSimpleFunction(expression.callee.object)
|
2635
2640
|
) {
|
2636
2641
|
// (function(…) { }.call/bind(?, …))
|
2637
2642
|
this._walkIIFE(
|
@@ -2639,7 +2644,10 @@ class JavascriptParser extends Parser {
|
|
2639
2644
|
expression.arguments.slice(1),
|
2640
2645
|
expression.arguments[0]
|
2641
2646
|
);
|
2642
|
-
} else if (
|
2647
|
+
} else if (
|
2648
|
+
expression.callee.type.endsWith("FunctionExpression") &&
|
2649
|
+
isSimpleFunction(expression.callee)
|
2650
|
+
) {
|
2643
2651
|
// (function(…) { }(…))
|
2644
2652
|
this._walkIIFE(expression.callee, expression.arguments, null);
|
2645
2653
|
} else {
|
@@ -3376,9 +3384,16 @@ class JavascriptParser extends Parser {
|
|
3376
3384
|
}
|
3377
3385
|
|
3378
3386
|
getComments(range) {
|
3379
|
-
|
3380
|
-
|
3381
|
-
);
|
3387
|
+
const [rangeStart, rangeEnd] = range;
|
3388
|
+
const compare = (comment, needle) => comment.range[0] - needle;
|
3389
|
+
let idx = binarySearchBounds.ge(this.comments, rangeStart, compare);
|
3390
|
+
let commentsInRange = [];
|
3391
|
+
while (this.comments[idx] && this.comments[idx].range[1] <= rangeEnd) {
|
3392
|
+
commentsInRange.push(this.comments[idx]);
|
3393
|
+
idx++;
|
3394
|
+
}
|
3395
|
+
|
3396
|
+
return commentsInRange;
|
3382
3397
|
}
|
3383
3398
|
|
3384
3399
|
/**
|
@@ -87,6 +87,7 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
|
|
87
87
|
* @property {string[] | "global"} prefix name prefix
|
88
88
|
* @property {string | false} declare declare name as variable
|
89
89
|
* @property {"error"|"copy"|"assign"} unnamed behavior for unnamed library name
|
90
|
+
* @property {"copy"|"assign"=} named behavior for named library name
|
90
91
|
*/
|
91
92
|
|
92
93
|
/**
|
@@ -94,6 +95,9 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
|
|
94
95
|
* @property {string | string[]} name
|
95
96
|
*/
|
96
97
|
|
98
|
+
const COMMON_LIBRARY_NAME_MESSAGE =
|
99
|
+
"Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.";
|
100
|
+
|
97
101
|
/**
|
98
102
|
* @typedef {AssignLibraryPluginParsed} T
|
99
103
|
* @extends {AbstractLibraryPlugin<AssignLibraryPluginParsed>}
|
@@ -110,6 +114,7 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
|
|
110
114
|
this.prefix = options.prefix;
|
111
115
|
this.declare = options.declare;
|
112
116
|
this.unnamed = options.unnamed;
|
117
|
+
this.named = options.named || "assign";
|
113
118
|
}
|
114
119
|
|
115
120
|
/**
|
@@ -120,11 +125,15 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
|
|
120
125
|
const { name } = library;
|
121
126
|
if (this.unnamed === "error") {
|
122
127
|
if (typeof name !== "string" && !Array.isArray(name)) {
|
123
|
-
throw new Error(
|
128
|
+
throw new Error(
|
129
|
+
`Library name must be a string or string array. ${COMMON_LIBRARY_NAME_MESSAGE}`
|
130
|
+
);
|
124
131
|
}
|
125
132
|
} else {
|
126
133
|
if (name && typeof name !== "string" && !Array.isArray(name)) {
|
127
|
-
throw new Error(
|
134
|
+
throw new Error(
|
135
|
+
`Library name must be a string, string array or unset. ${COMMON_LIBRARY_NAME_MESSAGE}`
|
136
|
+
);
|
128
137
|
}
|
129
138
|
}
|
130
139
|
return {
|
@@ -156,12 +165,12 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
|
|
156
165
|
throw new Error(
|
157
166
|
`Library name base (${base}) must be a valid identifier when using a var declaring library type. Either use a valid identifier (e. g. ${Template.toIdentifier(
|
158
167
|
base
|
159
|
-
)}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable).
|
168
|
+
)}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). ${COMMON_LIBRARY_NAME_MESSAGE}`
|
160
169
|
);
|
161
170
|
}
|
162
171
|
result.add(`${this.declare} ${base};`);
|
163
172
|
}
|
164
|
-
if (
|
173
|
+
if (options.name ? this.named === "copy" : this.unnamed === "copy") {
|
165
174
|
result.add(
|
166
175
|
`(function(e, a) { for(var i in a) e[i] = a[i]; if(a.__esModule) Object.defineProperty(e, "__esModule", { value: true }); }(${accessWithInit(
|
167
176
|
fullNameResolved,
|
@@ -87,6 +87,18 @@ class EnableLibraryPlugin {
|
|
87
87
|
}).apply(compiler);
|
88
88
|
break;
|
89
89
|
}
|
90
|
+
case "assign-properties": {
|
91
|
+
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
|
92
|
+
const AssignLibraryPlugin = require("./AssignLibraryPlugin");
|
93
|
+
new AssignLibraryPlugin({
|
94
|
+
type,
|
95
|
+
prefix: [],
|
96
|
+
declare: false,
|
97
|
+
unnamed: "error",
|
98
|
+
named: "copy"
|
99
|
+
}).apply(compiler);
|
100
|
+
break;
|
101
|
+
}
|
90
102
|
case "assign": {
|
91
103
|
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
|
92
104
|
const AssignLibraryPlugin = require("./AssignLibraryPlugin");
|