mirror of https://github.com/webpack/webpack.git
perf(buildChunkGraph): avoid unneeded re-visit
This commit is contained in:
commit
456c70432a
|
|
@ -38,6 +38,7 @@ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
|
||||||
* @typedef {object} ChunkGroupInfo
|
* @typedef {object} ChunkGroupInfo
|
||||||
* @property {ChunkGroup} chunkGroup the chunk group
|
* @property {ChunkGroup} chunkGroup the chunk group
|
||||||
* @property {RuntimeSpec} runtime the runtimes
|
* @property {RuntimeSpec} runtime the runtimes
|
||||||
|
* @property {boolean} init is this chunk group initialized
|
||||||
* @property {bigint | undefined} minAvailableModules current minimal set of modules available at this point
|
* @property {bigint | undefined} minAvailableModules current minimal set of modules available at this point
|
||||||
* @property {bigint[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
|
* @property {bigint[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
|
||||||
* @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
|
* @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
|
||||||
|
|
@ -345,8 +346,8 @@ const visitModules = (
|
||||||
/** @type {Map<DependenciesBlock, ChunkGroupInfo>} */
|
/** @type {Map<DependenciesBlock, ChunkGroupInfo>} */
|
||||||
const blockChunkGroups = new Map();
|
const blockChunkGroups = new Map();
|
||||||
|
|
||||||
/** @type {Map<ChunkGroupInfo, DependenciesBlock>} */
|
/** @type {Map<ChunkGroupInfo, Set<DependenciesBlock>>} */
|
||||||
const blockByChunkGroups = new Map();
|
const blocksByChunkGroups = new Map();
|
||||||
|
|
||||||
/** @type {Map<string, ChunkGroupInfo>} */
|
/** @type {Map<string, ChunkGroupInfo>} */
|
||||||
const namedChunkGroups = new Map();
|
const namedChunkGroups = new Map();
|
||||||
|
|
@ -367,7 +368,7 @@ const visitModules = (
|
||||||
/** @type {QueueItem[]} */
|
/** @type {QueueItem[]} */
|
||||||
let queue = [];
|
let queue = [];
|
||||||
|
|
||||||
/** @type {Map<ChunkGroupInfo, Set<ChunkGroupInfo>>} */
|
/** @type {Map<ChunkGroupInfo, Set<[ChunkGroupInfo, ChunkGroup, Module | null]>>} */
|
||||||
const queueConnect = new Map();
|
const queueConnect = new Map();
|
||||||
/** @type {Set<ChunkGroupInfo>} */
|
/** @type {Set<ChunkGroupInfo>} */
|
||||||
const chunkGroupsForCombining = new Set();
|
const chunkGroupsForCombining = new Set();
|
||||||
|
|
@ -382,6 +383,7 @@ const visitModules = (
|
||||||
);
|
);
|
||||||
/** @type {ChunkGroupInfo} */
|
/** @type {ChunkGroupInfo} */
|
||||||
const chunkGroupInfo = {
|
const chunkGroupInfo = {
|
||||||
|
init: false,
|
||||||
chunkGroup,
|
chunkGroup,
|
||||||
runtime,
|
runtime,
|
||||||
minAvailableModules: undefined,
|
minAvailableModules: undefined,
|
||||||
|
|
@ -452,7 +454,7 @@ const visitModules = (
|
||||||
|
|
||||||
/** @type {Set<ChunkGroupInfo>} */
|
/** @type {Set<ChunkGroupInfo>} */
|
||||||
const outdatedChunkGroupInfo = new Set();
|
const outdatedChunkGroupInfo = new Set();
|
||||||
/** @type {Set<ChunkGroupInfo>} */
|
/** @type {Set<[ChunkGroupInfo, ChunkGroup, Module | null]>} */
|
||||||
const chunkGroupsForMerging = new Set();
|
const chunkGroupsForMerging = new Set();
|
||||||
/** @type {QueueItem[]} */
|
/** @type {QueueItem[]} */
|
||||||
let queueDelayed = [];
|
let queueDelayed = [];
|
||||||
|
|
@ -505,6 +507,7 @@ const visitModules = (
|
||||||
entrypoint.index = nextChunkGroupIndex++;
|
entrypoint.index = nextChunkGroupIndex++;
|
||||||
cgi = {
|
cgi = {
|
||||||
chunkGroup: entrypoint,
|
chunkGroup: entrypoint,
|
||||||
|
init: false,
|
||||||
runtime: entrypoint.options.runtime || entrypoint.name,
|
runtime: entrypoint.options.runtime || entrypoint.name,
|
||||||
minAvailableModules: ZERO_BIGINT,
|
minAvailableModules: ZERO_BIGINT,
|
||||||
availableModulesToBeMerged: [],
|
availableModulesToBeMerged: [],
|
||||||
|
|
@ -572,6 +575,7 @@ const visitModules = (
|
||||||
maskByChunk.set(c.chunks[0], ZERO_BIGINT);
|
maskByChunk.set(c.chunks[0], ZERO_BIGINT);
|
||||||
c.index = nextChunkGroupIndex++;
|
c.index = nextChunkGroupIndex++;
|
||||||
cgi = {
|
cgi = {
|
||||||
|
init: false,
|
||||||
chunkGroup: c,
|
chunkGroup: c,
|
||||||
runtime: chunkGroupInfo.runtime,
|
runtime: chunkGroupInfo.runtime,
|
||||||
minAvailableModules: undefined,
|
minAvailableModules: undefined,
|
||||||
|
|
@ -614,7 +618,14 @@ const visitModules = (
|
||||||
blockConnections.set(b, []);
|
blockConnections.set(b, []);
|
||||||
}
|
}
|
||||||
blockChunkGroups.set(b, /** @type {ChunkGroupInfo} */ (cgi));
|
blockChunkGroups.set(b, /** @type {ChunkGroupInfo} */ (cgi));
|
||||||
blockByChunkGroups.set(/** @type {ChunkGroupInfo} */ (cgi), b);
|
let blocks = blocksByChunkGroups.get(/** @type {ChunkGroupInfo} */ (cgi));
|
||||||
|
if (!blocks) {
|
||||||
|
blocksByChunkGroups.set(
|
||||||
|
/** @type {ChunkGroupInfo} */ (cgi),
|
||||||
|
(blocks = new Set())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
blocks.add(b);
|
||||||
} else if (entryOptions) {
|
} else if (entryOptions) {
|
||||||
entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
|
entrypoint = /** @type {Entrypoint} */ (cgi.chunkGroup);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -636,19 +647,9 @@ const visitModules = (
|
||||||
connectList = new Set();
|
connectList = new Set();
|
||||||
queueConnect.set(chunkGroupInfo, connectList);
|
queueConnect.set(chunkGroupInfo, connectList);
|
||||||
}
|
}
|
||||||
connectList.add(/** @type {ChunkGroupInfo} */ (cgi));
|
connectList.add(
|
||||||
|
/** @type {[ChunkGroupInfo, ChunkGroup, Module]} */ ([cgi, c, module])
|
||||||
// TODO check if this really need to be done for each traversal
|
);
|
||||||
// or if it is enough when it's queued when created
|
|
||||||
// 4. We enqueue the DependenciesBlock for traversal
|
|
||||||
queueDelayed.push({
|
|
||||||
action: PROCESS_BLOCK,
|
|
||||||
block: b,
|
|
||||||
module,
|
|
||||||
chunk: c.chunks[0],
|
|
||||||
chunkGroup: c,
|
|
||||||
chunkGroupInfo: /** @type {ChunkGroupInfo} */ (cgi)
|
|
||||||
});
|
|
||||||
} else if (entrypoint !== undefined) {
|
} else if (entrypoint !== undefined) {
|
||||||
chunkGroupInfo.chunkGroup.addAsyncEntrypoint(entrypoint);
|
chunkGroupInfo.chunkGroup.addAsyncEntrypoint(entrypoint);
|
||||||
}
|
}
|
||||||
|
|
@ -901,11 +902,10 @@ const visitModules = (
|
||||||
for (const [chunkGroupInfo, targets] of queueConnect) {
|
for (const [chunkGroupInfo, targets] of queueConnect) {
|
||||||
// 1. Add new targets to the list of children
|
// 1. Add new targets to the list of children
|
||||||
if (chunkGroupInfo.children === undefined) {
|
if (chunkGroupInfo.children === undefined) {
|
||||||
chunkGroupInfo.children = targets;
|
chunkGroupInfo.children = new Set();
|
||||||
} else {
|
}
|
||||||
for (const target of targets) {
|
for (const [target] of targets) {
|
||||||
chunkGroupInfo.children.add(target);
|
chunkGroupInfo.children.add(target);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Calculate resulting available modules
|
// 2. Calculate resulting available modules
|
||||||
|
|
@ -915,9 +915,9 @@ const visitModules = (
|
||||||
const runtime = chunkGroupInfo.runtime;
|
const runtime = chunkGroupInfo.runtime;
|
||||||
|
|
||||||
// 3. Update chunk group info
|
// 3. Update chunk group info
|
||||||
for (const target of targets) {
|
for (const [target, chunkGroup, module] of targets) {
|
||||||
target.availableModulesToBeMerged.push(resultingAvailableModules);
|
target.availableModulesToBeMerged.push(resultingAvailableModules);
|
||||||
chunkGroupsForMerging.add(target);
|
chunkGroupsForMerging.add([target, chunkGroup, module]);
|
||||||
const oldRuntime = target.runtime;
|
const oldRuntime = target.runtime;
|
||||||
const newRuntime = mergeRuntime(oldRuntime, runtime);
|
const newRuntime = mergeRuntime(oldRuntime, runtime);
|
||||||
if (oldRuntime !== newRuntime) {
|
if (oldRuntime !== newRuntime) {
|
||||||
|
|
@ -935,7 +935,7 @@ const visitModules = (
|
||||||
statProcessedChunkGroupsForMerging += chunkGroupsForMerging.size;
|
statProcessedChunkGroupsForMerging += chunkGroupsForMerging.size;
|
||||||
|
|
||||||
// Execute the merge
|
// Execute the merge
|
||||||
for (const info of chunkGroupsForMerging) {
|
for (const [info, chunkGroup, module] of chunkGroupsForMerging) {
|
||||||
const availableModulesToBeMerged = info.availableModulesToBeMerged;
|
const availableModulesToBeMerged = info.availableModulesToBeMerged;
|
||||||
const cachedMinAvailableModules = info.minAvailableModules;
|
const cachedMinAvailableModules = info.minAvailableModules;
|
||||||
let minAvailableModules = cachedMinAvailableModules;
|
let minAvailableModules = cachedMinAvailableModules;
|
||||||
|
|
@ -958,6 +958,20 @@ const visitModules = (
|
||||||
info.resultingAvailableModules = undefined;
|
info.resultingAvailableModules = undefined;
|
||||||
outdatedChunkGroupInfo.add(info);
|
outdatedChunkGroupInfo.add(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!info.init || changed) && module) {
|
||||||
|
info.init = true;
|
||||||
|
for (const b of blocksByChunkGroups.get(info)) {
|
||||||
|
queueDelayed.push({
|
||||||
|
action: PROCESS_BLOCK,
|
||||||
|
block: b,
|
||||||
|
module,
|
||||||
|
chunk: chunkGroup.chunks[0],
|
||||||
|
chunkGroup,
|
||||||
|
chunkGroupInfo: info
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
chunkGroupsForMerging.clear();
|
chunkGroupsForMerging.clear();
|
||||||
};
|
};
|
||||||
|
|
@ -1057,7 +1071,7 @@ const visitModules = (
|
||||||
connectList = new Set();
|
connectList = new Set();
|
||||||
queueConnect.set(info, connectList);
|
queueConnect.set(info, connectList);
|
||||||
}
|
}
|
||||||
connectList.add(cgi);
|
connectList.add([cgi, cgi.chunkGroup, module]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1117,48 +1131,44 @@ const visitModules = (
|
||||||
for (const info of outdatedOrderIndexChunkGroups) {
|
for (const info of outdatedOrderIndexChunkGroups) {
|
||||||
const { chunkGroup, runtime } = info;
|
const { chunkGroup, runtime } = info;
|
||||||
|
|
||||||
const block = blockByChunkGroups.get(info);
|
const blocks = blocksByChunkGroups.get(info);
|
||||||
|
|
||||||
if (!block) {
|
if (!blocks) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let preOrderIndex = 0;
|
for (const block of blocks) {
|
||||||
let postOrderIndex = 0;
|
let preOrderIndex = 0;
|
||||||
|
let postOrderIndex = 0;
|
||||||
|
/**
|
||||||
|
* @param {DependenciesBlock} current current
|
||||||
|
* @param {BlocksWithNestedBlocks} visited visited dependencies blocks
|
||||||
|
*/
|
||||||
|
const process = (current, visited) => {
|
||||||
|
const blockModules = getBlockModules(current, runtime);
|
||||||
|
for (let i = 0, len = blockModules.length; i < len; i += 3) {
|
||||||
|
const activeState = /** @type {ConnectionState} */ (
|
||||||
|
blockModules[i + 1]
|
||||||
|
);
|
||||||
|
if (activeState === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const refModule = /** @type {Module} */ (blockModules[i]);
|
||||||
|
if (visited.has(refModule)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
visited.add(refModule);
|
||||||
* @param {DependenciesBlock} current current
|
|
||||||
* @param {BlocksWithNestedBlocks} visited visited dependencies blocks
|
|
||||||
*/
|
|
||||||
const process = (current, visited) => {
|
|
||||||
const blockModules = getBlockModules(current, runtime);
|
|
||||||
if (blockModules === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0, len = blockModules.length; i < len; i += 3) {
|
if (refModule) {
|
||||||
const activeState = /** @type {ConnectionState} */ (
|
chunkGroup.setModulePreOrderIndex(refModule, preOrderIndex++);
|
||||||
blockModules[i + 1]
|
process(refModule, visited);
|
||||||
);
|
chunkGroup.setModulePostOrderIndex(refModule, postOrderIndex++);
|
||||||
if (activeState === false) {
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
const refModule = /** @type {Module} */ (blockModules[i]);
|
};
|
||||||
if (visited.has(refModule)) {
|
process(block, new Set());
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
visited.add(refModule);
|
|
||||||
|
|
||||||
if (refModule) {
|
|
||||||
chunkGroup.setModulePreOrderIndex(refModule, preOrderIndex++);
|
|
||||||
process(refModule, visited);
|
|
||||||
chunkGroup.setModulePostOrderIndex(refModule, postOrderIndex++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
process(block, new Set());
|
|
||||||
}
|
}
|
||||||
outdatedOrderIndexChunkGroups.clear();
|
outdatedOrderIndexChunkGroups.clear();
|
||||||
ordinalByModule.clear();
|
ordinalByModule.clear();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
optimization: {
|
||||||
|
moduleIds: "named"
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue