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
+20
View File
@@ -683,6 +683,10 @@ export interface ResolveOptions {
fileSystem?: {
[k: string]: any;
};
/**
* Enable to ignore fatal errors happening during resolving of 'resolve.roots'. Usually such errors should not happen, but this option is provided for backward-compatibility.
*/
ignoreRootsErrors?: boolean;
/**
* Field names from the description file (package.json) which are used to find the default entry point
*/
@@ -703,12 +707,20 @@ export interface ResolveOptions {
* Plugins for the resolver
*/
plugins?: (WebpackPluginInstance | WebpackPluginFunction)[];
/**
* Prefer to resolve server-relative URLs (starting with '/') as absolute paths before falling back to resolve in 'resolve.roots'.
*/
preferAbsolute?: boolean;
/**
* Custom resolver
*/
resolver?: {
[k: string]: any;
};
/**
* A list of directories in which requests that are server-relative URLs (starting with '/') are resolved.
*/
roots?: string[];
/**
* Enable resolving symlinks to the original location
*/
@@ -927,6 +939,10 @@ export interface OptimizationSplitChunksOptions {
* Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group
*/
enforce?: boolean;
/**
* Size threshold at which splitting is enforced and other restrictions (maxAsyncRequests, maxInitialRequests) are ignored.
*/
enforceSizeThreshold?: number;
/**
* Sets the template for the filename for created chunks (Only works for initial chunks)
*/
@@ -973,6 +989,10 @@ export interface OptimizationSplitChunksOptions {
* Select chunks for determining shared modules (defaults to "async", "initial" and "all" requires adding these chunks to the HTML)
*/
chunks?: ("initial" | "async" | "all") | Function;
/**
* Size threshold at which splitting is enforced and other restrictions (maxAsyncRequests, maxInitialRequests) are ignored.
*/
enforceSizeThreshold?: number;
/**
* Options for modules not selected by any other cache group
*/
+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);
+10
View File
@@ -2,6 +2,16 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="6.0.2"></a>
## [6.0.2](https://github.com/zkat/ssri/compare/v6.0.1...v6.0.2) (2021-04-07)
### Bug Fixes
* backport regex change from 8.0.1 ([b30dfdb](https://github.com/zkat/ssri/commit/b30dfdb)), closes [#19](https://github.com/zkat/ssri/issues/19)
<a name="6.0.1"></a>
## [6.0.1](https://github.com/zkat/ssri/compare/v6.0.0...v6.0.1) (2018-08-27)
+1 -1
View File
@@ -8,7 +8,7 @@ const SPEC_ALGORITHMS = ['sha256', 'sha384', 'sha512']
const BASE64_REGEX = /^[a-z0-9+/]+(?:=?=?)$/i
const SRI_REGEX = /^([^-]+)-([^?]+)([?\S*]*)$/
const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)*$/
const STRICT_SRI_REGEX = /^([^-]+)-([A-Za-z0-9+/=]{44,88})(\?[\x21-\x7E]*)?$/
const VCHAR_REGEX = /^[\x21-\x7E]+$/
const SsriOpts = figgyPudding({
+12 -12
View File
@@ -1,32 +1,32 @@
{
"_args": [
[
"ssri@6.0.1",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
"ssri@6.0.2",
"/home/node/nuxt"
]
],
"_from": "ssri@6.0.1",
"_id": "ssri@6.0.1",
"_from": "ssri@6.0.2",
"_id": "ssri@6.0.2",
"_inBundle": false,
"_integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"_integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
"_location": "/webpack/ssri",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "ssri@6.0.1",
"raw": "ssri@6.0.2",
"name": "ssri",
"escapedName": "ssri",
"rawSpec": "6.0.1",
"rawSpec": "6.0.2",
"saveSpec": null,
"fetchSpec": "6.0.1"
"fetchSpec": "6.0.2"
},
"_requiredBy": [
"/webpack/cacache"
],
"_resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
"_spec": "6.0.1",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"_resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
"_spec": "6.0.2",
"_where": "/home/node/nuxt",
"author": {
"name": "Kat Marchán",
"email": "kzm@sykosomatic.org"
@@ -88,5 +88,5 @@
"update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'",
"update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'"
},
"version": "6.0.1"
"version": "6.0.2"
}
+26 -18
View File
@@ -1,19 +1,19 @@
{
"_args": [
[
"webpack@4.43.0",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
"webpack@4.46.0",
"/home/node/nuxt"
]
],
"_from": "webpack@4.43.0",
"_id": "webpack@4.43.0",
"_from": "webpack@4.46.0",
"_id": "webpack@4.46.0",
"_inBundle": false,
"_integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==",
"_integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
"_location": "/webpack",
"_phantomChildren": {
"ajv": "6.12.3",
"ajv": "6.12.6",
"ajv-errors": "1.0.1",
"ajv-keywords": "3.5.1",
"ajv-keywords": "3.5.2",
"arr-diff": "4.0.0",
"arr-flatten": "1.1.0",
"array-unique": "0.3.2",
@@ -25,7 +25,7 @@
"figgy-pudding": "3.5.2",
"find-cache-dir": "2.1.0",
"fragment-cache": "0.2.1",
"glob": "7.1.6",
"glob": "7.2.3",
"graceful-fs": "4.2.4",
"infer-owner": "1.0.4",
"is-buffer": "1.1.6",
@@ -54,24 +54,24 @@
"unique-filename": "1.1.1",
"webpack-sources": "1.4.3",
"worker-farm": "1.7.0",
"y18n": "4.0.0"
"y18n": "4.0.3"
},
"_requested": {
"type": "version",
"registry": true,
"raw": "webpack@4.43.0",
"raw": "webpack@4.46.0",
"name": "webpack",
"escapedName": "webpack",
"rawSpec": "4.43.0",
"rawSpec": "4.46.0",
"saveSpec": null,
"fetchSpec": "4.43.0"
"fetchSpec": "4.46.0"
},
"_requiredBy": [
"/@nuxt/webpack"
],
"_resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz",
"_spec": "4.43.0",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"_resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
"_spec": "4.46.0",
"_where": "/home/node/nuxt",
"author": {
"name": "Tobias Koppers @sokra"
},
@@ -90,7 +90,7 @@
"ajv": "^6.10.2",
"ajv-keywords": "^3.4.1",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^4.1.0",
"enhanced-resolve": "^4.5.0",
"eslint-scope": "^4.0.3",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^2.4.0",
@@ -103,7 +103,7 @@
"schema-utils": "^1.0.0",
"tapable": "^1.1.3",
"terser-webpack-plugin": "^1.4.3",
"watchpack": "^1.6.1",
"watchpack": "^1.7.4",
"webpack-sources": "^1.4.1"
},
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
@@ -241,6 +241,14 @@
},
"main": "lib/webpack.js",
"name": "webpack",
"peerDependenciesMeta": {
"webpack-cli": {
"optional": true
},
"webpack-command": {
"optional": true
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/webpack/webpack.git"
@@ -278,6 +286,6 @@
"travis:lintunit": "yarn lint && yarn cover:unit --ci $JEST",
"type-lint": "tsc --pretty"
},
"version": "4.43.0",
"version": "4.46.0",
"web": "lib/webpack.web.js"
}
+24
View File
@@ -612,6 +612,10 @@
"description": "Ignore minimum size, minimum chunks and maximum requests and always create chunks for this cache group",
"type": "boolean"
},
"enforceSizeThreshold": {
"description": "Size threshold at which splitting is enforced and other restrictions (maxAsyncRequests, maxInitialRequests) are ignored.",
"type": "number"
},
"filename": {
"description": "Sets the template for the filename for created chunks (Only works for initial chunks)",
"type": "string",
@@ -722,6 +726,10 @@
}
]
},
"enforceSizeThreshold": {
"description": "Size threshold at which splitting is enforced and other restrictions (maxAsyncRequests, maxInitialRequests) are ignored.",
"type": "number"
},
"fallbackCacheGroup": {
"description": "Options for modules not selected by any other cache group",
"type": "object",
@@ -1171,6 +1179,10 @@
"fileSystem": {
"description": "Filesystem for the resolver"
},
"ignoreRootsErrors": {
"description": "Enable to ignore fatal errors happening during resolving of 'resolve.roots'. Usually such errors should not happen, but this option is provided for backward-compatibility.",
"type": "boolean"
},
"mainFields": {
"description": "Field names from the description file (package.json) which are used to find the default entry point",
"anyOf": [
@@ -1218,9 +1230,21 @@
]
}
},
"preferAbsolute": {
"description": "Prefer to resolve server-relative URLs (starting with '/') as absolute paths before falling back to resolve in 'resolve.roots'.",
"type": "boolean"
},
"resolver": {
"description": "Custom resolver"
},
"roots": {
"description": "A list of directories in which requests that are server-relative URLs (starting with '/') are resolved.",
"type": "array",
"items": {
"description": "Directory in which requests that are server-relative URLs (starting with '/') are resolved.",
"type": "string"
}
},
"symlinks": {
"description": "Enable resolving symlinks to the original location",
"type": "boolean"