webpack 检出图 第 七 节 lib/ChunkGraph.js

🔧 Chunk 与 Entry Module 的连接管理

  • disconnectEntryModule(module)

    • 移除某模块在所有 chunk 中的 entry 角色。
    • 清除该模块记录的 entryInChunks
  • disconnectEntries(chunk)

    • 将指定 chunk 的所有 entry 模块解绑。
    • 更新对应模块的 entryInChunks,若为空则置为 undefined

🔢 Entry / Runtime Module 数量查询

  • getNumberOfEntryModules(chunk)

    • 获取 chunk 中的 entry 模块数量。
  • getNumberOfRuntimeModules(chunk)

    • 获取 chunk 中 runtime 模块的数量。

🔁 获取 chunk 中的模块集合(entry/runtime/hash)

  • getChunkEntryModulesIterable(chunk)

    • 返回 chunk 中所有 entry 模块(可迭代,不可修改)。
  • getChunkRuntimeModulesIterable(chunk)

    • 返回 chunk 中所有 runtime 模块(可迭代,不可修改)。
  • getChunkRuntimeModulesInOrder(chunk)

    • 返回按执行顺序排序的 runtime 模块数组。
  • getChunkFullHashModulesIterable(chunk)

    • 获取参与 chunk full hash 计算的模块(可迭代)。
  • getChunkFullHashModulesSet(chunk)

    • 获取参与 chunk full hash 计算的模块集合(只读)。
  • getChunkDependentHashModulesIterable(chunk)

    • 获取参与 dependent hash 的模块(可迭代)。
  • getChunkEntryModulesWithChunkGroupIterable(chunk)

    • 获取 chunk 中的 entry 模块及其对应 chunkGroup 信息。

🔁 Chunk 依赖关系管理(与其他 chunk 的关系)

  • getChunkEntryDependentChunksIterable(chunk)

    • 获取同一 entrypoint 下与该 chunk 相关但无 runtime 的 chunk。
  • hasChunkEntryDependentChunks(chunk)

    • 判断 chunk 是否还有 entryGroup 中的其他 chunk 存在依赖。

🔗 Async Block 与 ChunkGroup 映射关系

  • getBlockChunkGroup(depBlock)

    • 获取异步依赖块对应的 chunkGroup。
  • connectBlockAndChunkGroup(depBlock, chunkGroup)

    • 建立异步依赖块和 chunkGroup 的映射关系。
js 复制代码
/**
 * 断开某个模块与所有 chunk 的 entry 关系(该模块将不再作为 entry module 存在)
 * @param {Module} module the entry module, it will no longer be entry
 * @returns {void}
 */
disconnectEntryModule(module) {
	const cgm = this._getChunkGraphModule(module); // 获取模块的 ChunkGraphModule 实例
	for (const chunk of /** @type {EntryInChunks} */ (cgm.entryInChunks)) {
		const cgc = this._getChunkGraphChunk(chunk); // 获取 chunk 的 ChunkGraphChunk 实例
		cgc.entryModules.delete(module); // 从该 chunk 的 entryModules 中删除该模块
	}
	cgm.entryInChunks = undefined; // 清除模块记录的所有 entry 关联
}

/**
 * 将某个 chunk 的所有 entry module 全部断开
 * @param {Chunk} chunk the chunk, for which all entries will be removed
 * @returns {void}
 */
disconnectEntries(chunk) {
	const cgc = this._getChunkGraphChunk(chunk); // 获取 chunk 的 ChunkGraphChunk 实例
	for (const module of cgc.entryModules.keys()) {
		const cgm = this._getChunkGraphModule(module); // 获取模块的 ChunkGraphModule 实例
		(cgm.entryInChunks).delete(chunk); // 从模块的 entryInChunks 中删除该 chunk
		if ((cgm.entryInChunks).size === 0) {
			cgm.entryInChunks = undefined; // 若没有任何 chunk 关联,清除 entryInChunks
		}
	}
	cgc.entryModules.clear(); // 清除 chunk 上所有 entry 模块
}

/**
 * 获取 chunk 中的 entry 模块数量
 * @param {Chunk} chunk the chunk
 * @returns {number} the amount of entry modules in chunk
 */
getNumberOfEntryModules(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.entryModules.size;
}

/**
 * 获取 chunk 中的 runtime 模块数量
 * @param {Chunk} chunk the chunk
 * @returns {number} the amount of runtime modules in chunk
 */
getNumberOfRuntimeModules(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.runtimeModules.size;
}

/**
 * 获取 chunk 中的所有 entry 模块(返回可迭代对象)
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<Module>} iterable of modules (do not modify)
 */
getChunkEntryModulesIterable(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.entryModules.keys();
}

/**
 * 获取 chunk 所依赖的其他 chunk(同一个 entryPoint 下但非 runtime chunk)
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<Chunk>} iterable of chunks
 */
getChunkEntryDependentChunksIterable(chunk) {
	const set = new Set(); // 用于收集依赖的 chunk
	for (const chunkGroup of chunk.groupsIterable) {
		if (chunkGroup instanceof Entrypoint) {
			const entrypointChunk = chunkGroup.getEntrypointChunk(); // 获取入口 chunk
			const cgc = this._getChunkGraphChunk(entrypointChunk);
			for (const chunkGroup of cgc.entryModules.values()) {
				for (const c of chunkGroup.chunks) {
					if (c !== chunk && c !== entrypointChunk && !c.hasRuntime()) {
						set.add(c); // 添加非本身、非入口且不包含 runtime 的 chunk
					}
				}
			}
		}
	}
	return set;
}

/**
 * 判断该 chunk 是否有依赖的 chunk(entry 模块所在 chunkGroup 中存在其他 chunk)
 * @param {Chunk} chunk the chunk
 * @returns {boolean} true, when it has dependent chunks
 */
hasChunkEntryDependentChunks(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	for (const chunkGroup of cgc.entryModules.values()) {
		for (const c of chunkGroup.chunks) {
			if (c !== chunk) return true; // 存在其他 chunk 即返回 true
		}
	}
	return false;
}

/**
 * 获取 chunk 中的所有 runtime 模块(返回可迭代对象)
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<RuntimeModule>} iterable of modules (do not modify)
 */
getChunkRuntimeModulesIterable(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.runtimeModules;
}

/**
 * 获取 chunk 中按执行顺序排序的 runtime 模块数组
 * @param {Chunk} chunk the chunk
 * @returns {RuntimeModule[]} array of modules in order of execution
 */
getChunkRuntimeModulesInOrder(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	const array = Array.from(cgc.runtimeModules); // 复制为数组
	array.sort(
		concatComparators(
			compareSelect(r => /** @type {RuntimeModule} */ (r).stage, compareIds), // 优先按 stage 排序
			compareModulesByIdentifier // 再按模块标识符排序
		)
	);
	return array;
}

/**
 * 获取 chunk 中参与 full hash 计算的模块(返回可迭代对象)
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
 */
getChunkFullHashModulesIterable(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.fullHashModules;
}

/**
 * 获取 chunk 中参与 full hash 计算的模块集合(只读集合)
 * @param {Chunk} chunk the chunk
 * @returns {ReadonlySet<RuntimeModule> | undefined} set of modules (do not modify)
 */
getChunkFullHashModulesSet(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.fullHashModules;
}

/**
 * 获取 chunk 中参与 dependent hash 计算的模块(返回可迭代对象)
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify)
 */
getChunkDependentHashModulesIterable(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.dependentHashModules;
}

/**
 * 获取 chunk 中的 entry 模块及其对应的 chunkGroup 结构
 * @param {Chunk} chunk the chunk
 * @returns {Iterable<EntryModuleWithChunkGroup>} iterable of modules (do not modify)
 */
getChunkEntryModulesWithChunkGroupIterable(chunk) {
	const cgc = this._getChunkGraphChunk(chunk);
	return cgc.entryModules;
}

/**
 * 获取某个异步依赖块对应的 chunkGroup
 * @param {AsyncDependenciesBlock} depBlock the async block
 * @returns {ChunkGroup | undefined} the chunk group
 */
getBlockChunkGroup(depBlock) {
	return this._blockChunkGroups.get(depBlock);
}

/**
 * 将异步依赖块与 chunkGroup 建立连接关系
 * @param {AsyncDependenciesBlock} depBlock the async block
 * @param {ChunkGroup} chunkGroup the chunk group
 * @returns {void}
 */
connectBlockAndChunkGroup(depBlock, chunkGroup) {
	this._blockChunkGroups.set(depBlock, chunkGroup); // 记录映射关系
	chunkGroup.addBlock(depBlock); // 添加该 block 到 chunkGroup
}
相关推荐
拉不动的猪1 小时前
无缝适配 PC 和移动端‌我们要注意哪些点呢
前端·javascript·面试
酱酱们的每日掘金2 小时前
🔥 4 月精选:AICoding Cursor上新与 MCP 实战揭秘!- AI Coding 周刊第 5 期
前端·ai编程·mcp
天天扭码2 小时前
一分钟解决 | 高频面试算法题——和为 K 的子数组(前缀和)
前端·算法·面试
搞瓶可乐2 小时前
鸿蒙ArkUI之布局实战,线性布局(Column,Row)、弹性布局(Flex)、层叠布局(Stack),详细用法
前端·harmonyos·鸿蒙系统·arkui·弹性布局·布局实战·堆叠布局
Aphasia3112 小时前
小厂面试常考算法题整合(一)✍🏻
前端·算法·面试
五月仲夏3 小时前
React基础知识(补充中)
前端·react.js·前端框架
王富贵的记录3 小时前
React 函数组件和类组件的区别
前端·javascript·react.js
yuhaiqiang3 小时前
在公司写代码是工作,在开源社区写代码是生活
前端·后端
左耳咚3 小时前
Egg.js 服务端 HTML 强缓存问题排查与解决
前端·egg.js
DevUI团队3 小时前
Electron 入门学习指南:快速搭建跨平台桌面应用
前端·javascript·electron