webpack 5.66.0 → 5.69.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.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/README.md +1 -1
- package/lib/APIPlugin.js +33 -0
- package/lib/Cache.js +1 -1
- package/lib/CacheFacade.js +2 -2
- package/lib/ChunkGraph.js +1 -2
- package/lib/CleanPlugin.js +1 -1
- package/lib/Compilation.js +14 -9
- package/lib/Compiler.js +57 -3
- package/lib/ContextModule.js +21 -17
- package/lib/DelegatedModule.js +1 -1
- package/lib/DependencyTemplates.js +1 -1
- package/lib/DllModule.js +1 -1
- package/lib/EvalDevToolModulePlugin.js +16 -1
- package/lib/EvalSourceMapDevToolPlugin.js +18 -1
- package/lib/ExportsInfo.js +4 -4
- package/lib/ExternalModule.js +1 -1
- package/lib/ExternalModuleFactoryPlugin.js +1 -1
- package/lib/FileSystemInfo.js +29 -25
- package/lib/HookWebpackError.js +1 -1
- package/lib/Module.js +1 -3
- package/lib/MultiCompiler.js +1 -1
- package/lib/MultiWatching.js +1 -1
- package/lib/NormalModule.js +6 -4
- package/lib/NormalModuleFactory.js +25 -27
- package/lib/ProgressPlugin.js +1 -1
- package/lib/RawModule.js +1 -1
- package/lib/RuntimeGlobals.js +18 -0
- package/lib/RuntimeModule.js +1 -1
- package/lib/RuntimePlugin.js +28 -3
- package/lib/RuntimeTemplate.js +1 -1
- package/lib/TemplatedPathPlugin.js +48 -23
- package/lib/Watching.js +1 -1
- package/lib/WebpackOptionsApply.js +1 -1
- package/lib/asset/AssetGenerator.js +65 -26
- package/lib/asset/AssetModulesPlugin.js +3 -0
- package/lib/asset/RawDataUrlModule.js +8 -5
- package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
- package/lib/buildChunkGraph.js +1 -1
- package/lib/cache/ResolverCachePlugin.js +1 -1
- package/lib/cli.js +44 -3
- package/lib/config/defaults.js +30 -7
- package/lib/config/normalization.js +5 -0
- package/lib/container/ContainerEntryModule.js +4 -2
- package/lib/container/FallbackModule.js +4 -4
- package/lib/container/RemoteModule.js +4 -2
- package/lib/css/CssExportsGenerator.js +139 -0
- package/lib/css/CssGenerator.js +3 -0
- package/lib/css/CssLoadingRuntimeModule.js +201 -154
- package/lib/css/CssModulesPlugin.js +22 -4
- package/lib/debug/ProfilingPlugin.js +15 -14
- package/lib/dependencies/ContextElementDependency.js +8 -2
- package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
- package/lib/dependencies/ExportsInfoDependency.js +6 -0
- package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -5
- package/lib/dependencies/ImportMetaPlugin.js +22 -3
- package/lib/dependencies/LoaderPlugin.js +2 -2
- package/lib/hmr/LazyCompilationPlugin.js +45 -21
- package/lib/hmr/lazyCompilationBackend.js +1 -1
- package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
- package/lib/ids/HashedModuleIdsPlugin.js +9 -12
- package/lib/ids/IdHelpers.js +24 -10
- package/lib/ids/NamedModuleIdsPlugin.js +6 -9
- package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
- package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
- package/lib/ids/SyncModuleIdsPlugin.js +140 -0
- package/lib/index.js +10 -0
- package/lib/javascript/JavascriptModulesPlugin.js +27 -2
- package/lib/javascript/StartupHelpers.js +3 -2
- package/lib/library/AssignLibraryPlugin.js +8 -2
- package/lib/node/NodeTargetPlugin.js +1 -0
- package/lib/optimize/ConcatenatedModule.js +11 -5
- package/lib/runtime/AsyncModuleRuntimeModule.js +25 -15
- package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
- package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
- package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
- package/lib/schemes/HttpUriPlugin.js +32 -11
- package/lib/serialization/FileMiddleware.js +44 -9
- package/lib/sharing/ConsumeSharedModule.js +4 -2
- package/lib/sharing/ProvideSharedModule.js +4 -2
- package/lib/sharing/utils.js +1 -1
- package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
- package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
- package/lib/util/ArrayHelpers.js +18 -4
- package/lib/util/AsyncQueue.js +1 -1
- package/lib/util/compileBooleanMatcher.js +1 -1
- package/lib/util/deterministicGrouping.js +1 -1
- package/lib/util/identifier.js +65 -44
- package/lib/util/nonNumericOnlyHash.js +22 -0
- package/lib/util/semver.js +17 -10
- package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +9 -3
- package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
- package/package.json +14 -21
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +47 -6
- package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
- package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
- package/types.d.ts +207 -60
@@ -19,10 +19,13 @@ const { compareModulesByIdentifier } = require("../util/comparators");
|
|
19
19
|
const createSchemaValidation = require("../util/create-schema-validation");
|
20
20
|
const createHash = require("../util/createHash");
|
21
21
|
const memoize = require("../util/memoize");
|
22
|
+
const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
|
23
|
+
const CssExportsGenerator = require("./CssExportsGenerator");
|
22
24
|
const CssGenerator = require("./CssGenerator");
|
23
25
|
const CssParser = require("./CssParser");
|
24
26
|
|
25
27
|
/** @typedef {import("webpack-sources").Source} Source */
|
28
|
+
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
|
26
29
|
/** @typedef {import("../Chunk")} Chunk */
|
27
30
|
/** @typedef {import("../Compiler")} Compiler */
|
28
31
|
/** @typedef {import("../Module")} Module */
|
@@ -70,6 +73,12 @@ const escapeCss = (str, omitOptionalUnderscore) => {
|
|
70
73
|
const plugin = "CssModulesPlugin";
|
71
74
|
|
72
75
|
class CssModulesPlugin {
|
76
|
+
/**
|
77
|
+
* @param {CssExperimentOptions} options options
|
78
|
+
*/
|
79
|
+
constructor({ exportsOnly = false }) {
|
80
|
+
this._exportsOnly = exportsOnly;
|
81
|
+
}
|
73
82
|
/**
|
74
83
|
* Apply the plugin
|
75
84
|
* @param {Compiler} compiler the compiler instance
|
@@ -143,19 +152,25 @@ class CssModulesPlugin {
|
|
143
152
|
.for("css")
|
144
153
|
.tap(plugin, generatorOptions => {
|
145
154
|
validateGeneratorOptions(generatorOptions);
|
146
|
-
return
|
155
|
+
return this._exportsOnly
|
156
|
+
? new CssExportsGenerator()
|
157
|
+
: new CssGenerator();
|
147
158
|
});
|
148
159
|
normalModuleFactory.hooks.createGenerator
|
149
160
|
.for("css/global")
|
150
161
|
.tap(plugin, generatorOptions => {
|
151
162
|
validateGeneratorOptions(generatorOptions);
|
152
|
-
return
|
163
|
+
return this._exportsOnly
|
164
|
+
? new CssExportsGenerator()
|
165
|
+
: new CssGenerator();
|
153
166
|
});
|
154
167
|
normalModuleFactory.hooks.createGenerator
|
155
168
|
.for("css/module")
|
156
169
|
.tap(plugin, generatorOptions => {
|
157
170
|
validateGeneratorOptions(generatorOptions);
|
158
|
-
return
|
171
|
+
return this._exportsOnly
|
172
|
+
? new CssExportsGenerator()
|
173
|
+
: new CssGenerator();
|
159
174
|
});
|
160
175
|
const orderedCssModulesPerChunk = new WeakMap();
|
161
176
|
compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
|
@@ -187,7 +202,7 @@ class CssModulesPlugin {
|
|
187
202
|
hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
|
188
203
|
}
|
189
204
|
const digest = /** @type {string} */ (hash.digest(hashDigest));
|
190
|
-
chunk.contentHash.css = digest
|
205
|
+
chunk.contentHash.css = nonNumericOnlyHash(digest, hashDigestLength);
|
191
206
|
});
|
192
207
|
compilation.hooks.renderManifest.tap(plugin, (result, options) => {
|
193
208
|
const { chunkGraph } = compilation;
|
@@ -238,6 +253,9 @@ class CssModulesPlugin {
|
|
238
253
|
const CssLoadingRuntimeModule = getCssLoadingRuntimeModule();
|
239
254
|
compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set));
|
240
255
|
};
|
256
|
+
compilation.hooks.runtimeRequirementInTree
|
257
|
+
.for(RuntimeGlobals.hasCssModules)
|
258
|
+
.tap(plugin, handler);
|
241
259
|
compilation.hooks.runtimeRequirementInTree
|
242
260
|
.for(RuntimeGlobals.ensureChunkHandlers)
|
243
261
|
.tap(plugin, handler);
|
@@ -123,9 +123,7 @@ class Profiler {
|
|
123
123
|
* @returns {Trace} The trace object
|
124
124
|
*/
|
125
125
|
const createTrace = (fs, outputPath) => {
|
126
|
-
const trace = new Tracer(
|
127
|
-
noStream: true
|
128
|
-
});
|
126
|
+
const trace = new Tracer();
|
129
127
|
const profiler = new Profiler(inspector);
|
130
128
|
if (/\/|\\/.test(outputPath)) {
|
131
129
|
const dirPath = dirname(fs, outputPath);
|
@@ -173,6 +171,7 @@ const createTrace = (fs, outputPath) => {
|
|
173
171
|
counter,
|
174
172
|
profiler,
|
175
173
|
end: callback => {
|
174
|
+
trace.push("]");
|
176
175
|
// Wait until the write stream finishes.
|
177
176
|
fsStream.on("close", () => {
|
178
177
|
callback();
|
@@ -242,10 +241,10 @@ class ProfilingPlugin {
|
|
242
241
|
stage: Infinity
|
243
242
|
},
|
244
243
|
(stats, callback) => {
|
244
|
+
if (compiler.watchMode) return callback();
|
245
245
|
tracer.profiler.stopProfiling().then(parsedResults => {
|
246
246
|
if (parsedResults === undefined) {
|
247
247
|
tracer.profiler.destroy();
|
248
|
-
tracer.trace.flush();
|
249
248
|
tracer.end(callback);
|
250
249
|
return;
|
251
250
|
}
|
@@ -293,7 +292,6 @@ class ProfilingPlugin {
|
|
293
292
|
});
|
294
293
|
|
295
294
|
tracer.profiler.destroy();
|
296
|
-
tracer.trace.flush();
|
297
295
|
tracer.end(callback);
|
298
296
|
});
|
299
297
|
}
|
@@ -345,16 +343,19 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
|
|
345
343
|
};
|
346
344
|
|
347
345
|
const makeInterceptorFor = (instance, tracer) => hookName => ({
|
348
|
-
register:
|
349
|
-
const
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
346
|
+
register: tapInfo => {
|
347
|
+
const { name, type, fn } = tapInfo;
|
348
|
+
const newFn =
|
349
|
+
// Don't tap our own hooks to ensure stream can close cleanly
|
350
|
+
name === pluginName
|
351
|
+
? fn
|
352
|
+
: makeNewProfiledTapFn(hookName, tracer, {
|
353
|
+
name,
|
354
|
+
type,
|
355
|
+
fn
|
356
|
+
});
|
354
357
|
return {
|
355
|
-
|
356
|
-
type,
|
357
|
-
context,
|
358
|
+
...tapInfo,
|
358
359
|
fn: newFn
|
359
360
|
};
|
360
361
|
}
|
@@ -53,12 +53,18 @@ class ContextElementDependency extends ModuleDependency {
|
|
53
53
|
}
|
54
54
|
|
55
55
|
serialize(context) {
|
56
|
-
context
|
56
|
+
const { write } = context;
|
57
|
+
write(this._typePrefix);
|
58
|
+
write(this._category);
|
59
|
+
write(this.referencedExports);
|
57
60
|
super.serialize(context);
|
58
61
|
}
|
59
62
|
|
60
63
|
deserialize(context) {
|
61
|
-
|
64
|
+
const { read } = context;
|
65
|
+
this._typePrefix = read();
|
66
|
+
this._category = read();
|
67
|
+
this.referencedExports = read();
|
62
68
|
super.deserialize(context);
|
63
69
|
}
|
64
70
|
}
|
@@ -25,6 +25,18 @@ class CreateScriptUrlDependency extends NullDependency {
|
|
25
25
|
get type() {
|
26
26
|
return "create script url";
|
27
27
|
}
|
28
|
+
|
29
|
+
serialize(context) {
|
30
|
+
const { write } = context;
|
31
|
+
write(this.range);
|
32
|
+
super.serialize(context);
|
33
|
+
}
|
34
|
+
|
35
|
+
deserialize(context) {
|
36
|
+
const { read } = context;
|
37
|
+
this.range = read();
|
38
|
+
super.deserialize(context);
|
39
|
+
}
|
28
40
|
}
|
29
41
|
|
30
42
|
CreateScriptUrlDependency.Template = class CreateScriptUrlDependencyTemplate extends (
|
@@ -46,6 +46,12 @@ const getProperty = (moduleGraph, module, exportName, property, runtime) => {
|
|
46
46
|
}
|
47
47
|
}
|
48
48
|
switch (property) {
|
49
|
+
case "canMangle": {
|
50
|
+
const exportsInfo = moduleGraph.getExportsInfo(module);
|
51
|
+
const exportInfo = exportsInfo.getExportInfo(exportName);
|
52
|
+
if (exportInfo) return exportInfo.canMangle;
|
53
|
+
return exportsInfo.otherExportsInfo.canMangle;
|
54
|
+
}
|
49
55
|
case "used":
|
50
56
|
return (
|
51
57
|
moduleGraph.getExportsInfo(module).getUsed(exportName, runtime) !==
|
@@ -74,14 +74,14 @@ HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate
|
|
74
74
|
initFragments.push(
|
75
75
|
new InitFragment(
|
76
76
|
runtimeTemplate.supportsArrowFunction()
|
77
|
-
? `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async (__webpack_handle_async_dependencies__) => {\n`
|
78
|
-
: `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async function (__webpack_handle_async_dependencies__) {\n`,
|
77
|
+
? `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n`
|
78
|
+
: `${RuntimeGlobals.asyncModule}(${module.moduleArgument}, async function (__webpack_handle_async_dependencies__, __webpack_async_result__) { try {\n`,
|
79
79
|
InitFragment.STAGE_ASYNC_BOUNDARY,
|
80
80
|
0,
|
81
81
|
undefined,
|
82
|
-
|
83
|
-
?
|
84
|
-
|
82
|
+
`\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }${
|
83
|
+
module.buildMeta.async ? ", 1" : ""
|
84
|
+
});`
|
85
85
|
)
|
86
86
|
);
|
87
87
|
}
|
@@ -20,6 +20,7 @@ const propertyAccess = require("../util/propertyAccess");
|
|
20
20
|
const ConstDependency = require("./ConstDependency");
|
21
21
|
|
22
22
|
/** @typedef {import("estree").MemberExpression} MemberExpression */
|
23
|
+
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
|
23
24
|
/** @typedef {import("../Compiler")} Compiler */
|
24
25
|
/** @typedef {import("../NormalModule")} NormalModule */
|
25
26
|
/** @typedef {import("../javascript/JavascriptParser")} Parser */
|
@@ -44,11 +45,29 @@ class ImportMetaPlugin {
|
|
44
45
|
return pathToFileURL(module.resource).toString();
|
45
46
|
};
|
46
47
|
/**
|
47
|
-
* @param {Parser} parser parser
|
48
|
-
* @param {
|
48
|
+
* @param {Parser} parser parser parser
|
49
|
+
* @param {JavascriptParserOptions} parserOptions parserOptions
|
49
50
|
* @returns {void}
|
50
51
|
*/
|
51
|
-
const parserHandler = (parser,
|
52
|
+
const parserHandler = (parser, { importMeta }) => {
|
53
|
+
if (importMeta === false) {
|
54
|
+
const { importMetaName } = compilation.outputOptions;
|
55
|
+
if (importMetaName === "import.meta") return;
|
56
|
+
|
57
|
+
parser.hooks.expression
|
58
|
+
.for("import.meta")
|
59
|
+
.tap("ImportMetaPlugin", metaProperty => {
|
60
|
+
const dep = new ConstDependency(
|
61
|
+
importMetaName,
|
62
|
+
metaProperty.range
|
63
|
+
);
|
64
|
+
dep.loc = metaProperty.loc;
|
65
|
+
parser.state.module.addPresentationalDependency(dep);
|
66
|
+
return true;
|
67
|
+
});
|
68
|
+
return;
|
69
|
+
}
|
70
|
+
|
52
71
|
/// import.meta direct ///
|
53
72
|
parser.hooks.typeof
|
54
73
|
.for("import.meta")
|
@@ -16,7 +16,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
|
|
16
16
|
|
17
17
|
/**
|
18
18
|
* @callback LoadModuleCallback
|
19
|
-
* @param {Error=} err error object
|
19
|
+
* @param {(Error | null)=} err error object
|
20
20
|
* @param {string | Buffer=} source source code
|
21
21
|
* @param {object=} map source map
|
22
22
|
* @param {Module=} module loaded module if successful
|
@@ -24,7 +24,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
|
|
24
24
|
|
25
25
|
/**
|
26
26
|
* @callback ImportModuleCallback
|
27
|
-
* @param {Error=} err error object
|
27
|
+
* @param {(Error | null)=} err error object
|
28
28
|
* @param {any=} exports exports of the evaluated module
|
29
29
|
*/
|
30
30
|
|
@@ -29,6 +29,7 @@ const { registerNotSerializable } = require("../util/serialization");
|
|
29
29
|
/** @typedef {import("../RequestShortener")} RequestShortener */
|
30
30
|
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
|
31
31
|
/** @typedef {import("../WebpackError")} WebpackError */
|
32
|
+
/** @typedef {import("../dependencies/HarmonyImportDependency")} HarmonyImportDependency */
|
32
33
|
/** @typedef {import("../util/Hash")} Hash */
|
33
34
|
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
|
34
35
|
|
@@ -38,7 +39,7 @@ const { registerNotSerializable } = require("../util/serialization");
|
|
38
39
|
* @property {function(Module): { client: string, data: string, active: boolean }} module
|
39
40
|
*/
|
40
41
|
|
41
|
-
const
|
42
|
+
const HMR_DEPENDENCY_TYPES = new Set([
|
42
43
|
"import.meta.webpackHot.accept",
|
43
44
|
"import.meta.webpackHot.decline",
|
44
45
|
"module.hot.accept",
|
@@ -146,7 +147,7 @@ class LazyCompilationProxyModule extends Module {
|
|
146
147
|
|
147
148
|
/**
|
148
149
|
* @param {NeedBuildContext} context context info
|
149
|
-
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
150
|
+
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
|
150
151
|
* @returns {void}
|
151
152
|
*/
|
152
153
|
needBuild(context, callback) {
|
@@ -351,32 +352,55 @@ class LazyCompilationPlugin {
|
|
351
352
|
"LazyCompilationPlugin",
|
352
353
|
(originalModule, createData, resolveData) => {
|
353
354
|
if (
|
354
|
-
resolveData.dependencies.every(
|
355
|
+
resolveData.dependencies.every(dep =>
|
356
|
+
HMR_DEPENDENCY_TYPES.has(dep.type)
|
357
|
+
)
|
358
|
+
) {
|
359
|
+
// for HMR only resolving, try to determine if the HMR accept/decline refers to
|
360
|
+
// an import() or not
|
361
|
+
const hmrDep = resolveData.dependencies[0];
|
362
|
+
const originModule =
|
363
|
+
compilation.moduleGraph.getParentModule(hmrDep);
|
364
|
+
const isReferringToDynamicImport = originModule.blocks.some(
|
365
|
+
block =>
|
366
|
+
block.dependencies.some(
|
367
|
+
dep =>
|
368
|
+
dep.type === "import()" &&
|
369
|
+
/** @type {HarmonyImportDependency} */ (dep).request ===
|
370
|
+
hmrDep.request
|
371
|
+
)
|
372
|
+
);
|
373
|
+
if (!isReferringToDynamicImport) return;
|
374
|
+
} else if (
|
375
|
+
!resolveData.dependencies.every(
|
355
376
|
dep =>
|
356
|
-
|
377
|
+
HMR_DEPENDENCY_TYPES.has(dep.type) ||
|
357
378
|
(this.imports &&
|
358
379
|
(dep.type === "import()" ||
|
359
380
|
dep.type === "import() context element")) ||
|
360
381
|
(this.entries && dep.type === "entry")
|
361
|
-
)
|
362
|
-
|
382
|
+
)
|
383
|
+
)
|
384
|
+
return;
|
385
|
+
if (
|
386
|
+
/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client|webpack-hot-middleware[/\\]client/.test(
|
363
387
|
resolveData.request
|
364
|
-
)
|
365
|
-
checkTest(this.test, originalModule)
|
366
|
-
)
|
367
|
-
|
368
|
-
|
369
|
-
|
388
|
+
) ||
|
389
|
+
!checkTest(this.test, originalModule)
|
390
|
+
)
|
391
|
+
return;
|
392
|
+
const moduleInfo = backend.module(originalModule);
|
393
|
+
if (!moduleInfo) return;
|
394
|
+
const { client, data, active } = moduleInfo;
|
370
395
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
}
|
396
|
+
return new LazyCompilationProxyModule(
|
397
|
+
compiler.context,
|
398
|
+
originalModule,
|
399
|
+
resolveData.request,
|
400
|
+
client,
|
401
|
+
data,
|
402
|
+
active
|
403
|
+
);
|
380
404
|
}
|
381
405
|
);
|
382
406
|
compilation.dependencyFactories.set(
|
@@ -9,7 +9,7 @@ const {
|
|
9
9
|
compareModulesByPreOrderIndexOrIdentifier
|
10
10
|
} = require("../util/comparators");
|
11
11
|
const {
|
12
|
-
|
12
|
+
getUsedModuleIdsAndModules,
|
13
13
|
getFullModuleName,
|
14
14
|
assignDeterministicIds
|
15
15
|
} = require("./IdHelpers");
|
@@ -18,8 +18,17 @@ const {
|
|
18
18
|
/** @typedef {import("../Module")} Module */
|
19
19
|
|
20
20
|
class DeterministicModuleIdsPlugin {
|
21
|
-
|
22
|
-
|
21
|
+
/**
|
22
|
+
* @param {Object} options options
|
23
|
+
* @param {string=} options.context context relative to which module identifiers are computed
|
24
|
+
* @param {function(Module): boolean=} options.test selector function for modules
|
25
|
+
* @param {number=} options.maxLength maximum id length in digits (used as starting point)
|
26
|
+
* @param {number=} options.salt hash salt for ids
|
27
|
+
* @param {boolean=} options.fixedLength do not increase the maxLength to find an optimal id space size
|
28
|
+
* @param {boolean=} options.failOnConflict throw an error when id conflicts occur (instead of rehashing)
|
29
|
+
*/
|
30
|
+
constructor(options = {}) {
|
31
|
+
this.options = options;
|
23
32
|
}
|
24
33
|
|
25
34
|
/**
|
@@ -31,40 +40,51 @@ class DeterministicModuleIdsPlugin {
|
|
31
40
|
compiler.hooks.compilation.tap(
|
32
41
|
"DeterministicModuleIdsPlugin",
|
33
42
|
compilation => {
|
34
|
-
compilation.hooks.moduleIds.tap(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
compilation.hooks.moduleIds.tap("DeterministicModuleIdsPlugin", () => {
|
44
|
+
const chunkGraph = compilation.chunkGraph;
|
45
|
+
const context = this.options.context
|
46
|
+
? this.options.context
|
47
|
+
: compiler.context;
|
48
|
+
const maxLength = this.options.maxLength || 3;
|
49
|
+
const failOnConflict = this.options.failOnConflict || false;
|
50
|
+
const fixedLength = this.options.fixedLength || false;
|
51
|
+
const salt = this.options.salt || 0;
|
52
|
+
let conflicts = 0;
|
42
53
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
compareModulesByPreOrderIndexOrIdentifier(
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
return
|
61
|
-
}
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
const [usedIds, modules] = getUsedModuleIdsAndModules(
|
55
|
+
compilation,
|
56
|
+
this.options.test
|
57
|
+
);
|
58
|
+
assignDeterministicIds(
|
59
|
+
modules,
|
60
|
+
module => getFullModuleName(module, context, compiler.root),
|
61
|
+
failOnConflict
|
62
|
+
? () => 0
|
63
|
+
: compareModulesByPreOrderIndexOrIdentifier(
|
64
|
+
compilation.moduleGraph
|
65
|
+
),
|
66
|
+
(module, id) => {
|
67
|
+
const size = usedIds.size;
|
68
|
+
usedIds.add(`${id}`);
|
69
|
+
if (size === usedIds.size) {
|
70
|
+
conflicts++;
|
71
|
+
return false;
|
72
|
+
}
|
73
|
+
chunkGraph.setModuleId(module, id);
|
74
|
+
return true;
|
75
|
+
},
|
76
|
+
[Math.pow(10, maxLength)],
|
77
|
+
fixedLength ? 0 : 10,
|
78
|
+
usedIds.size,
|
79
|
+
salt
|
80
|
+
);
|
81
|
+
if (failOnConflict && conflicts)
|
82
|
+
throw new Error(
|
83
|
+
`Assigning deterministic module ids has lead to ${conflicts} conflict${
|
84
|
+
conflicts > 1 ? "s" : ""
|
85
|
+
}.\nIncrease the 'maxLength' to increase the id space and make conflicts less likely (recommended when there are many conflicts or application is expected to grow), or add an 'salt' number to try another hash starting value in the same id space (recommended when there is only a single conflict).`
|
65
86
|
);
|
66
|
-
|
67
|
-
);
|
87
|
+
});
|
68
88
|
}
|
69
89
|
);
|
70
90
|
}
|
@@ -10,7 +10,10 @@ const {
|
|
10
10
|
} = require("../util/comparators");
|
11
11
|
const createSchemaValidation = require("../util/create-schema-validation");
|
12
12
|
const createHash = require("../util/createHash");
|
13
|
-
const {
|
13
|
+
const {
|
14
|
+
getUsedModuleIdsAndModules,
|
15
|
+
getFullModuleName
|
16
|
+
} = require("./IdHelpers");
|
14
17
|
|
15
18
|
/** @typedef {import("../../declarations/plugins/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
|
16
19
|
|
@@ -43,22 +46,16 @@ class HashedModuleIdsPlugin {
|
|
43
46
|
apply(compiler) {
|
44
47
|
const options = this.options;
|
45
48
|
compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => {
|
46
|
-
compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin",
|
49
|
+
compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", () => {
|
47
50
|
const chunkGraph = compilation.chunkGraph;
|
48
51
|
const context = this.options.context
|
49
52
|
? this.options.context
|
50
53
|
: compiler.context;
|
51
54
|
|
52
|
-
const usedIds =
|
53
|
-
const modulesInNaturalOrder =
|
54
|
-
.
|
55
|
-
|
56
|
-
if (chunkGraph.getNumberOfModuleChunks(m) === 0) return false;
|
57
|
-
return chunkGraph.getModuleId(module) === null;
|
58
|
-
})
|
59
|
-
.sort(
|
60
|
-
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
|
61
|
-
);
|
55
|
+
const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
|
56
|
+
const modulesInNaturalOrder = modules.sort(
|
57
|
+
compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
|
58
|
+
);
|
62
59
|
for (const module of modulesInNaturalOrder) {
|
63
60
|
const ident = getFullModuleName(module, context, compiler.root);
|
64
61
|
const hash = createHash(options.hashFunction);
|
package/lib/ids/IdHelpers.js
CHANGED
@@ -234,11 +234,14 @@ const addToMapOfItems = (map, key, value) => {
|
|
234
234
|
|
235
235
|
/**
|
236
236
|
* @param {Compilation} compilation the compilation
|
237
|
-
* @
|
237
|
+
* @param {function(Module): boolean=} filter filter modules
|
238
|
+
* @returns {[Set<string>, Module[]]} used module ids as strings and modules without id matching the filter
|
238
239
|
*/
|
239
|
-
const
|
240
|
+
const getUsedModuleIdsAndModules = (compilation, filter) => {
|
240
241
|
const chunkGraph = compilation.chunkGraph;
|
241
242
|
|
243
|
+
const modules = [];
|
244
|
+
|
242
245
|
/** @type {Set<string>} */
|
243
246
|
const usedIds = new Set();
|
244
247
|
if (compilation.usedModuleIds) {
|
@@ -248,15 +251,23 @@ const getUsedModuleIds = compilation => {
|
|
248
251
|
}
|
249
252
|
|
250
253
|
for (const module of compilation.modules) {
|
254
|
+
if (!module.needId) continue;
|
251
255
|
const moduleId = chunkGraph.getModuleId(module);
|
252
256
|
if (moduleId !== null) {
|
253
257
|
usedIds.add(moduleId + "");
|
258
|
+
} else {
|
259
|
+
if (
|
260
|
+
(!filter || filter(module)) &&
|
261
|
+
chunkGraph.getNumberOfModuleChunks(module) !== 0
|
262
|
+
) {
|
263
|
+
modules.push(module);
|
264
|
+
}
|
254
265
|
}
|
255
266
|
}
|
256
267
|
|
257
|
-
return usedIds;
|
268
|
+
return [usedIds, modules];
|
258
269
|
};
|
259
|
-
exports.
|
270
|
+
exports.getUsedModuleIdsAndModules = getUsedModuleIdsAndModules;
|
260
271
|
|
261
272
|
/**
|
262
273
|
* @param {Compilation} compilation the compilation
|
@@ -359,6 +370,7 @@ exports.assignNames = assignNames;
|
|
359
370
|
* @param {number[]} ranges usable ranges for ids
|
360
371
|
* @param {number} expandFactor factor to create more ranges
|
361
372
|
* @param {number} extraSpace extra space to allocate, i. e. when some ids are already used
|
373
|
+
* @param {number} salt salting number to initialize hashing
|
362
374
|
* @returns {void}
|
363
375
|
*/
|
364
376
|
const assignDeterministicIds = (
|
@@ -368,7 +380,8 @@ const assignDeterministicIds = (
|
|
368
380
|
assignId,
|
369
381
|
ranges = [10],
|
370
382
|
expandFactor = 10,
|
371
|
-
extraSpace = 0
|
383
|
+
extraSpace = 0,
|
384
|
+
salt = 0
|
372
385
|
) => {
|
373
386
|
items.sort(comparator);
|
374
387
|
|
@@ -384,15 +397,17 @@ const assignDeterministicIds = (
|
|
384
397
|
i++;
|
385
398
|
if (i < ranges.length) {
|
386
399
|
range = Math.min(ranges[i], Number.MAX_SAFE_INTEGER);
|
387
|
-
} else {
|
400
|
+
} else if (expandFactor) {
|
388
401
|
range = Math.min(range * expandFactor, Number.MAX_SAFE_INTEGER);
|
402
|
+
} else {
|
403
|
+
break;
|
389
404
|
}
|
390
405
|
}
|
391
406
|
|
392
407
|
for (const item of items) {
|
393
408
|
const ident = getName(item);
|
394
409
|
let id;
|
395
|
-
let i =
|
410
|
+
let i = salt;
|
396
411
|
do {
|
397
412
|
id = numberHash(ident + i++, range);
|
398
413
|
} while (!assignId(item, id));
|
@@ -401,15 +416,14 @@ const assignDeterministicIds = (
|
|
401
416
|
exports.assignDeterministicIds = assignDeterministicIds;
|
402
417
|
|
403
418
|
/**
|
419
|
+
* @param {Set<string>} usedIds used ids
|
404
420
|
* @param {Iterable<Module>} modules the modules
|
405
421
|
* @param {Compilation} compilation the compilation
|
406
422
|
* @returns {void}
|
407
423
|
*/
|
408
|
-
const assignAscendingModuleIds = (modules, compilation) => {
|
424
|
+
const assignAscendingModuleIds = (usedIds, modules, compilation) => {
|
409
425
|
const chunkGraph = compilation.chunkGraph;
|
410
426
|
|
411
|
-
const usedIds = getUsedModuleIds(compilation);
|
412
|
-
|
413
427
|
let nextId = 0;
|
414
428
|
let assignId;
|
415
429
|
if (usedIds.size > 0) {
|