This commit is contained in:
2022-07-18 02:50:52 +00:00
parent befd344ab0
commit 06181b34d6
8569 changed files with 818704 additions and 352705 deletions
+28 -22
View File
@@ -129,28 +129,34 @@ class RecordIdsPlugin {
const sources = [];
for (const chunkGroup of chunk.groupsIterable) {
const index = chunkGroup.chunks.indexOf(chunk);
for (const origin of chunkGroup.origins) {
if (origin.module) {
if (origin.request) {
sources.push(
`${index} ${getModuleIdentifier(origin.module)} ${
origin.request
}`
);
} else if (typeof origin.loc === "string") {
sources.push(
`${index} ${getModuleIdentifier(origin.module)} ${origin.loc}`
);
} else if (
origin.loc &&
typeof origin.loc === "object" &&
origin.loc.start
) {
sources.push(
`${index} ${getModuleIdentifier(
origin.module
)} ${JSON.stringify(origin.loc.start)}`
);
if (chunkGroup.name) {
sources.push(`${index} ${chunkGroup.name}`);
} else {
for (const origin of chunkGroup.origins) {
if (origin.module) {
if (origin.request) {
sources.push(
`${index} ${getModuleIdentifier(origin.module)} ${
origin.request
}`
);
} else if (typeof origin.loc === "string") {
sources.push(
`${index} ${getModuleIdentifier(origin.module)} ${
origin.loc
}`
);
} else if (
origin.loc &&
typeof origin.loc === "object" &&
origin.loc.start
) {
sources.push(
`${index} ${getModuleIdentifier(
origin.module
)} ${JSON.stringify(origin.loc.start)}`
);
}
}
}
}
+11
View File
@@ -356,6 +356,17 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
options.resolve.plugins.length > 0
);
});
this.set(
"resolve.preferAbsolute",
"make",
options => !options.resolve.roots || options.resolve.roots.length === 0
);
this.set(
"resolve.ignoreRootsErrors",
"make",
options => !options.resolve.roots || options.resolve.roots.length === 0
);
this.set("resolve.roots", "make", options => [options.context]);
this.set("resolveLoader", "call", value => Object.assign({}, value));
this.set("resolveLoader.unsafeCache", true);
+44 -56
View File
@@ -38,8 +38,8 @@ const GraphHelpers = require("./GraphHelpers");
*/
/**
* @typedef {Object} ChunkGroupDep
* @property {AsyncDependenciesBlock} block referencing block
* @typedef {Object} BlockChunkGroupConnection
* @property {ChunkGroupInfo} originChunkGroupInfo origin chunk group
* @property {ChunkGroup} chunkGroup referenced chunk group
*/
@@ -143,7 +143,7 @@ const extraceBlockInfoMap = compilation => {
* @param {Compilation} compilation the compilation
* @param {Entrypoint[]} inputChunkGroups input groups
* @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkDependencies dependencies for chunk groups
* @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
* @param {Set<ChunkGroup>} allCreatedChunkGroups filled with all chunk groups that are created here
*/
@@ -151,7 +151,7 @@ const visitModules = (
compilation,
inputChunkGroups,
chunkGroupInfoMap,
chunkDependencies,
blockConnections,
blocksWithNestedBlocks,
allCreatedChunkGroups
) => {
@@ -229,6 +229,8 @@ const visitModules = (
let chunk;
/** @type {ChunkGroup} */
let chunkGroup;
/** @type {ChunkGroupInfo} */
let chunkGroupInfo;
/** @type {DependenciesBlock} */
let block;
/** @type {Set<Module>} */
@@ -263,17 +265,17 @@ const visitModules = (
blockChunkGroups.set(b, c);
allCreatedChunkGroups.add(c);
}
blockConnections.set(b, []);
} else {
// TODO webpack 5 remove addOptions check
if (c.addOptions) c.addOptions(b.groupOptions);
c.addOrigin(module, b.loc, b.request);
}
// 2. We store the Block+Chunk mapping as dependency for the chunk
let deps = chunkDependencies.get(chunkGroup);
if (!deps) chunkDependencies.set(chunkGroup, (deps = []));
deps.push({
block: b,
// 2. We store the connection for the block
// to connect it later if needed
blockConnections.get(b).push({
originChunkGroupInfo: chunkGroupInfo,
chunkGroup: c
});
@@ -306,7 +308,7 @@ const visitModules = (
chunk = queueItem.chunk;
if (chunkGroup !== queueItem.chunkGroup) {
chunkGroup = queueItem.chunkGroup;
const chunkGroupInfo = chunkGroupInfoMap.get(chunkGroup);
chunkGroupInfo = chunkGroupInfoMap.get(chunkGroup);
minAvailableModules = chunkGroupInfo.minAvailableModules;
skippedItems = chunkGroupInfo.skippedItems;
}
@@ -583,17 +585,14 @@ const visitModules = (
/**
*
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkDependencies dependencies for chunk groups
* @param {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} blockConnections connection for blocks
* @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
*/
const connectChunkGroups = (
blocksWithNestedBlocks,
chunkDependencies,
blockConnections,
chunkGroupInfoMap
) => {
/** @type {Set<Module>} */
let resultingAvailableModules;
/**
* Helper function to check if all modules of a chunk are available
*
@@ -611,49 +610,38 @@ const connectChunkGroups = (
};
// For each edge in the basic chunk graph
/**
* @param {ChunkGroupDep} dep the dependency used for filtering
* @returns {boolean} used to filter "edges" (aka Dependencies) that were pointing
* to modules that are already available. Also filters circular dependencies in the chunks graph
*/
const filterFn = dep => {
const depChunkGroup = dep.chunkGroup;
// TODO is this needed?
if (blocksWithNestedBlocks.has(dep.block)) return true;
if (areModulesAvailable(depChunkGroup, resultingAvailableModules)) {
return false; // break all modules are already available
for (const [block, connections] of blockConnections) {
// 1. Check if connection is needed
// When none of the dependencies need to be connected
// we can skip all of them
// It's not possible to filter each item so it doesn't create inconsistent
// connections and modules can only create one version
// TODO maybe decide this per runtime
if (
// TODO is this needed?
!blocksWithNestedBlocks.has(block) &&
connections.every(({ chunkGroup, originChunkGroupInfo }) =>
areModulesAvailable(
chunkGroup,
originChunkGroupInfo.resultingAvailableModules
)
)
) {
continue;
}
return true;
};
// For all deps, check if chunk groups need to be connected
for (const [chunkGroup, deps] of chunkDependencies) {
if (deps.length === 0) continue;
// 1. Get info from chunk group info map
const info = chunkGroupInfoMap.get(chunkGroup);
resultingAvailableModules = info.resultingAvailableModules;
// 2. Foreach edge
for (let i = 0; i < deps.length; i++) {
const dep = deps[i];
for (let i = 0; i < connections.length; i++) {
const { chunkGroup, originChunkGroupInfo } = connections[i];
// Filter inline, rather than creating a new array from `.filter()`
// TODO check if inlining filterFn makes sense here
if (!filterFn(dep)) {
continue;
}
const depChunkGroup = dep.chunkGroup;
const depBlock = dep.block;
// 3. Connect block with chunk
GraphHelpers.connectDependenciesBlockAndChunkGroup(block, chunkGroup);
// 5. Connect block with chunk
GraphHelpers.connectDependenciesBlockAndChunkGroup(
depBlock,
depChunkGroup
// 4. Connect chunk with parent
GraphHelpers.connectChunkGroupParentAndChild(
originChunkGroupInfo.chunkGroup,
chunkGroup
);
// 6. Connect chunk with parent
GraphHelpers.connectChunkGroupParentAndChild(chunkGroup, depChunkGroup);
}
}
};
@@ -685,8 +673,8 @@ const cleanupUnconnectedGroups = (compilation, allCreatedChunkGroups) => {
const buildChunkGraph = (compilation, inputChunkGroups) => {
// SHARED STATE
/** @type {Map<ChunkGroup, ChunkGroupDep[]>} */
const chunkDependencies = new Map();
/** @type {Map<AsyncDependenciesBlock, BlockChunkGroupConnection[]>} */
const blockConnections = new Map();
/** @type {Set<ChunkGroup>} */
const allCreatedChunkGroups = new Set();
@@ -703,7 +691,7 @@ const buildChunkGraph = (compilation, inputChunkGroups) => {
compilation,
inputChunkGroups,
chunkGroupInfoMap,
chunkDependencies,
blockConnections,
blocksWithNestedBlocks,
allCreatedChunkGroups
);
@@ -712,7 +700,7 @@ const buildChunkGraph = (compilation, inputChunkGroups) => {
connectChunkGroups(
blocksWithNestedBlocks,
chunkDependencies,
blockConnections,
chunkGroupInfoMap
);
@@ -27,6 +27,8 @@ class ExportMode {
this.name = null;
/** @type {Map<string, string>} */
this.map = EMPTY_MAP;
/** @type {Set<string>|null} */
this.ignored = null;
/** @type {Module|null} */
this.module = null;
/** @type {string|null} */
@@ -212,6 +214,11 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
const mode = new ExportMode("dynamic-reexport");
mode.module = importedModule;
mode.ignored = new Set([
"default",
...this.activeExports,
...activeFromOtherStarExports
]);
return mode;
}
@@ -580,10 +587,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
.join("");
case "dynamic-reexport": {
const activeExports = new Set([
...dep.activeExports,
...dep._discoverActiveExportsFromOtherStartExports()
]);
const ignoredExports = mode.ignored;
let content =
"/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " +
importVar +
@@ -591,10 +595,10 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS
// Filter out exports which are defined by other exports
// and filter out default export because it cannot be reexported with *
if (activeExports.size > 0) {
if (ignoredExports.size > 0) {
content +=
"if(" +
JSON.stringify(Array.from(activeExports).concat("default")) +
JSON.stringify(Array.from(ignoredExports)) +
".indexOf(__WEBPACK_IMPORT_KEY__) < 0) ";
} else {
content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') ";
+208 -25
View File
@@ -16,8 +16,89 @@ const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportS
* @typedef {Object} ExportInModule
* @property {Module} module the module
* @property {string} exportName the name of the export
* @property {boolean} checked if the export is conditional
*/
/**
* @typedef {Object} ReexportInfo
* @property {Map<string, ExportInModule[]>} static
* @property {Map<Module, Set<string>>} dynamic
*/
/**
* @param {ReexportInfo} info info object
* @param {string} exportName name of export
* @returns {ExportInModule | undefined} static export
*/
const getMappingFromInfo = (info, exportName) => {
const staticMappings = info.static.get(exportName);
if (staticMappings !== undefined) {
if (staticMappings.length === 1) return staticMappings[0];
return undefined;
}
const dynamicMappings = Array.from(info.dynamic).filter(
([_, ignored]) => !ignored.has(exportName)
);
if (dynamicMappings.length === 1) {
return {
module: dynamicMappings[0][0],
exportName,
checked: true
};
}
return undefined;
};
/**
* @param {ReexportInfo} info info object
* @param {string} exportName name of export of source module
* @param {Module} module the target module
* @param {string} innerExportName name of export of target module
* @param {boolean} checked true, if existence of target module is checked
*/
const addStaticReexport = (
info,
exportName,
module,
innerExportName,
checked
) => {
let mappings = info.static.get(exportName);
if (mappings !== undefined) {
for (const mapping of mappings) {
if (mapping.module === module && mapping.exportName === innerExportName) {
mapping.checked = mapping.checked && checked;
return;
}
}
} else {
mappings = [];
info.static.set(exportName, mappings);
}
mappings.push({
module,
exportName: innerExportName,
checked
});
};
/**
* @param {ReexportInfo} info info object
* @param {Module} module the reexport module
* @param {Set<string>} ignored ignore list
* @returns {void}
*/
const addDynamicReexport = (info, module, ignored) => {
const existingList = info.dynamic.get(module);
if (existingList !== undefined) {
for (const key of existingList) {
if (!ignored.has(key)) existingList.delete(key);
}
} else {
info.dynamic.set(module, new Set(ignored));
}
};
class SideEffectsFlagPlugin {
apply(compiler) {
compiler.hooks.normalModuleFactory.tap("SideEffectsFlagPlugin", nmf => {
@@ -52,7 +133,7 @@ class SideEffectsFlagPlugin {
compilation.hooks.optimizeDependencies.tap(
"SideEffectsFlagPlugin",
modules => {
/** @type {Map<Module, Map<string, ExportInModule>>} */
/** @type {Map<Module, ReexportInfo>} */
const reexportMaps = new Map();
// Capture reexports of sideEffectFree modules
@@ -69,16 +150,66 @@ class SideEffectsFlagPlugin {
) {
if (module.factoryMeta.sideEffectFree) {
const mode = dep.getMode(true);
if (mode.type === "safe-reexport") {
let map = reexportMaps.get(module);
if (!map) {
reexportMaps.set(module, (map = new Map()));
if (
mode.type === "safe-reexport" ||
mode.type === "checked-reexport" ||
mode.type === "dynamic-reexport" ||
mode.type === "reexport-non-harmony-default" ||
mode.type === "reexport-non-harmony-default-strict" ||
mode.type === "reexport-named-default"
) {
let info = reexportMaps.get(module);
if (!info) {
reexportMaps.set(
module,
(info = {
static: new Map(),
dynamic: new Map()
})
);
}
for (const pair of mode.map) {
map.set(pair[0], {
module: mode.module,
exportName: pair[1]
});
const targetModule = dep._module;
switch (mode.type) {
case "safe-reexport":
for (const [key, id] of mode.map) {
if (id) {
addStaticReexport(
info,
key,
targetModule,
id,
false
);
}
}
break;
case "checked-reexport":
for (const [key, id] of mode.map) {
if (id) {
addStaticReexport(
info,
key,
targetModule,
id,
true
);
}
}
break;
case "dynamic-reexport":
addDynamicReexport(info, targetModule, mode.ignored);
break;
case "reexport-non-harmony-default":
case "reexport-non-harmony-default-strict":
case "reexport-named-default":
addStaticReexport(
info,
mode.name,
targetModule,
"default",
false
);
break;
}
}
}
@@ -87,17 +218,68 @@ class SideEffectsFlagPlugin {
}
// Flatten reexports
for (const map of reexportMaps.values()) {
for (const pair of map) {
let mapping = pair[1];
while (mapping) {
const innerMap = reexportMaps.get(mapping.module);
if (!innerMap) break;
const newMapping = innerMap.get(mapping.exportName);
if (newMapping) {
map.set(pair[0], newMapping);
for (const info of reexportMaps.values()) {
const dynamicReexports = info.dynamic;
info.dynamic = new Map();
for (const reexport of dynamicReexports) {
let [targetModule, ignored] = reexport;
for (;;) {
const innerInfo = reexportMaps.get(targetModule);
if (!innerInfo) break;
for (const [key, reexports] of innerInfo.static) {
if (ignored.has(key)) continue;
for (const { module, exportName, checked } of reexports) {
addStaticReexport(info, key, module, exportName, checked);
}
}
mapping = newMapping;
// Follow dynamic reexport if there is only one
if (innerInfo.dynamic.size !== 1) {
// When there are more then one, we don't know which one
break;
}
ignored = new Set(ignored);
for (const [innerModule, innerIgnored] of innerInfo.dynamic) {
for (const key of innerIgnored) {
if (ignored.has(key)) continue;
// This reexports ends here
addStaticReexport(info, key, targetModule, key, true);
ignored.add(key);
}
targetModule = innerModule;
}
}
// Update reexport as all other cases has been handled
addDynamicReexport(info, targetModule, ignored);
}
}
for (const info of reexportMaps.values()) {
const staticReexports = info.static;
info.static = new Map();
for (const [key, reexports] of staticReexports) {
for (let mapping of reexports) {
for (;;) {
const innerInfo = reexportMaps.get(mapping.module);
if (!innerInfo) break;
const newMapping = getMappingFromInfo(
innerInfo,
mapping.exportName
);
if (!newMapping) break;
mapping = newMapping;
}
addStaticReexport(
info,
key,
mapping.module,
mapping.exportName,
mapping.checked
);
}
}
}
@@ -105,17 +287,18 @@ class SideEffectsFlagPlugin {
// Update imports along the reexports from sideEffectFree modules
for (const pair of reexportMaps) {
const module = pair[0];
const map = pair[1];
const info = pair[1];
let newReasons = undefined;
for (let i = 0; i < module.reasons.length; i++) {
const reason = module.reasons[i];
const dep = reason.dependency;
if (
dep instanceof HarmonyExportImportedSpecifierDependency ||
(dep instanceof HarmonyImportSpecifierDependency &&
!dep.namespaceObjectAsContext)
(dep instanceof HarmonyExportImportedSpecifierDependency ||
(dep instanceof HarmonyImportSpecifierDependency &&
!dep.namespaceObjectAsContext)) &&
dep._id
) {
const mapping = map.get(dep._id);
const mapping = getMappingFromInfo(info, dep._id);
if (mapping) {
dep.redirectedModule = mapping.module;
dep.redirectedId = mapping.exportName;
+86 -52
View File
@@ -75,12 +75,15 @@ const compareEntries = (a, b) => {
const bSizeReduce = b.size * (b.chunks.size - 1);
const diffSizeReduce = aSizeReduce - bSizeReduce;
if (diffSizeReduce) return diffSizeReduce;
// 4. by number of modules (to be able to compare by identifier)
// 4. by cache group index
const indexDiff = b.cacheGroupIndex - a.cacheGroupIndex;
if (indexDiff) return indexDiff;
// 5. by number of modules (to be able to compare by identifier)
const modulesA = a.modules;
const modulesB = b.modules;
const diff = modulesA.size - modulesB.size;
if (diff) return diff;
// 5. by module identifiers
// 6. by module identifiers
modulesA.sort();
modulesB.sort();
const aI = modulesA[Symbol.iterator]();
@@ -114,6 +117,7 @@ module.exports = class SplitChunksPlugin {
options.chunks || "all"
),
minSize: options.minSize || 0,
enforceSizeThreshold: options.enforceSizeThreshold || 0,
maxSize: options.maxSize || 0,
minChunks: options.minChunks || 1,
maxAsyncRequests: options.maxAsyncRequests || 1,
@@ -286,6 +290,7 @@ module.exports = class SplitChunksPlugin {
),
enforce: option.enforce,
minSize: option.minSize,
enforceSizeThreshold: option.enforceSizeThreshold,
maxSize: option.maxSize,
minChunks: option.minChunks,
maxAsyncRequests: option.maxAsyncRequests,
@@ -458,8 +463,8 @@ module.exports = class SplitChunksPlugin {
* @typedef {Object} ChunksInfoItem
* @property {SortableSet} modules
* @property {TODO} cacheGroup
* @property {number} cacheGroupIndex
* @property {string} name
* @property {boolean} validateSize
* @property {number} size
* @property {Set<Chunk>} chunks
* @property {Set<Chunk>} reuseableChunks
@@ -473,6 +478,7 @@ module.exports = class SplitChunksPlugin {
/**
* @param {TODO} cacheGroup the current cache group
* @param {number} cacheGroupIndex the index of the cache group of ordering
* @param {Chunk[]} selectedChunks chunks selected for this module
* @param {string} selectedChunksKey a key of selectedChunks
* @param {Module} module the current module
@@ -480,6 +486,7 @@ module.exports = class SplitChunksPlugin {
*/
const addModuleToChunksInfoMap = (
cacheGroup,
cacheGroupIndex,
selectedChunks,
selectedChunksKey,
module
@@ -507,8 +514,8 @@ module.exports = class SplitChunksPlugin {
(info = {
modules: new SortableSet(undefined, sortByIdentifier),
cacheGroup,
cacheGroupIndex,
name,
validateSize: cacheGroup.minSize > 0,
size: 0,
chunks: new Set(),
reuseableChunks: new Set(),
@@ -516,12 +523,14 @@ module.exports = class SplitChunksPlugin {
})
);
}
const oldSize = info.modules.size;
info.modules.add(module);
if (info.validateSize) {
if (info.modules.size !== oldSize) {
info.size += module.size();
}
if (!info.chunksKeys.has(selectedChunksKey)) {
info.chunksKeys.add(selectedChunksKey);
const oldChunksKeysSize = info.chunksKeys.size;
info.chunksKeys.add(selectedChunksKey);
if (oldChunksKeysSize !== info.chunksKeys.size) {
for (const chunk of selectedChunks) {
info.chunks.add(chunk);
}
@@ -544,22 +553,31 @@ module.exports = class SplitChunksPlugin {
combinationsCache.set(chunksKey, combs);
}
let cacheGroupIndex = 0;
for (const cacheGroupSource of cacheGroups) {
const minSize =
cacheGroupSource.minSize !== undefined
? cacheGroupSource.minSize
: cacheGroupSource.enforce
? 0
: this.options.minSize;
const enforceSizeThreshold =
cacheGroupSource.enforceSizeThreshold !== undefined
? cacheGroupSource.enforceSizeThreshold
: cacheGroupSource.enforce
? 0
: this.options.enforceSizeThreshold;
const cacheGroup = {
key: cacheGroupSource.key,
priority: cacheGroupSource.priority || 0,
chunksFilter:
cacheGroupSource.chunksFilter || this.options.chunksFilter,
minSize:
cacheGroupSource.minSize !== undefined
? cacheGroupSource.minSize
: cacheGroupSource.enforce
? 0
: this.options.minSize,
minSize,
minSizeForMaxSize:
cacheGroupSource.minSize !== undefined
? cacheGroupSource.minSize
: this.options.minSize,
enforceSizeThreshold,
maxSize:
cacheGroupSource.maxSize !== undefined
? cacheGroupSource.maxSize
@@ -596,7 +614,9 @@ module.exports = class SplitChunksPlugin {
cacheGroupSource.automaticNameDelimiter !== undefined
? cacheGroupSource.automaticNameDelimiter
: this.options.automaticNameDelimiter,
reuseExistingChunk: cacheGroupSource.reuseExistingChunk
reuseExistingChunk: cacheGroupSource.reuseExistingChunk,
_validateSize: minSize > 0,
_conditionalEnforce: enforceSizeThreshold > 0
};
// For all combination of chunk selection
for (const chunkCombination of combs) {
@@ -613,18 +633,23 @@ module.exports = class SplitChunksPlugin {
addModuleToChunksInfoMap(
cacheGroup,
cacheGroupIndex,
selectedChunks,
selectedChunksKey,
module
);
}
cacheGroupIndex++;
}
}
// Filter items were size < minSize
for (const pair of chunksInfoMap) {
const info = pair[1];
if (info.validateSize && info.size < info.cacheGroup.minSize) {
if (
info.cacheGroup._validateSize &&
info.size < info.cacheGroup.minSize
) {
chunksInfoMap.delete(pair[0]);
}
}
@@ -684,24 +709,30 @@ module.exports = class SplitChunksPlugin {
}
// Check if maxRequests condition can be fulfilled
const usedChunks = Array.from(item.chunks).filter(chunk => {
const selectedChunks = Array.from(item.chunks).filter(chunk => {
// skip if we address ourself
return (
(!chunkName || chunk.name !== chunkName) && chunk !== newChunk
);
});
const enforced =
item.cacheGroup._conditionalEnforce &&
item.size >= item.cacheGroup.enforceSizeThreshold;
// Skip when no chunk selected
if (usedChunks.length === 0) continue;
if (selectedChunks.length === 0) continue;
let validChunks = usedChunks;
const usedChunks = new Set(selectedChunks);
// Check if maxRequests condition can be fulfilled
if (
Number.isFinite(item.cacheGroup.maxInitialRequests) ||
Number.isFinite(item.cacheGroup.maxAsyncRequests)
!enforced &&
(Number.isFinite(item.cacheGroup.maxInitialRequests) ||
Number.isFinite(item.cacheGroup.maxAsyncRequests))
) {
validChunks = validChunks.filter(chunk => {
// respect max requests when not enforced
for (const chunk of usedChunks) {
// respect max requests
const maxRequests = chunk.isOnlyInitial()
? item.cacheGroup.maxInitialRequests
: chunk.canBeInitial()
@@ -710,26 +741,33 @@ module.exports = class SplitChunksPlugin {
item.cacheGroup.maxAsyncRequests
)
: item.cacheGroup.maxAsyncRequests;
return (
!isFinite(maxRequests) || getRequests(chunk) < maxRequests
);
});
if (
isFinite(maxRequests) &&
getRequests(chunk) >= maxRequests
) {
usedChunks.delete(chunk);
}
}
}
validChunks = validChunks.filter(chunk => {
outer: for (const chunk of usedChunks) {
for (const module of item.modules) {
if (chunk.containsModule(module)) return true;
if (chunk.containsModule(module)) continue outer;
}
return false;
});
usedChunks.delete(chunk);
}
if (validChunks.length < usedChunks.length) {
if (validChunks.length >= item.cacheGroup.minChunks) {
// Were some (invalid) chunks removed from usedChunks?
// => readd all modules to the queue, as things could have been changed
if (usedChunks.size < selectedChunks.length) {
if (usedChunks.size >= item.cacheGroup.minChunks) {
const chunksArr = Array.from(usedChunks);
for (const module of item.modules) {
addModuleToChunksInfoMap(
item.cacheGroup,
validChunks,
getKey(validChunks),
item.cacheGroupIndex,
chunksArr,
getKey(usedChunks),
module
);
}
@@ -819,28 +857,24 @@ module.exports = class SplitChunksPlugin {
// remove all modules from other entries and update size
for (const [key, info] of chunksInfoMap) {
if (isOverlap(info.chunks, item.chunks)) {
if (info.validateSize) {
// update modules and total size
// may remove it from the map when < minSize
const oldSize = info.modules.size;
for (const module of item.modules) {
info.modules.delete(module);
}
if (isOverlap(info.chunks, usedChunks)) {
// update modules and total size
// may remove it from the map when < minSize
const oldSize = info.modules.size;
for (const module of item.modules) {
info.modules.delete(module);
}
if (info.modules.size !== oldSize) {
if (info.modules.size === 0) {
chunksInfoMap.delete(key);
continue;
}
if (info.modules.size !== oldSize) {
info.size = getModulesSize(info.modules);
if (info.size < info.cacheGroup.minSize) {
chunksInfoMap.delete(key);
}
}
} else {
// only update the modules
for (const module of item.modules) {
info.modules.delete(module);
info.size = getModulesSize(info.modules);
if (
info.cacheGroup._validateSize &&
info.size < info.cacheGroup.minSize
) {
chunksInfoMap.delete(key);
}
if (info.modules.size === 0) {
chunksInfoMap.delete(key);