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
}
相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端