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
}
相关推荐
阿山同学.16 分钟前
AWS 亚马逊 S3存储桶直传 前端demo 复制即可使用
前端·javascript·aws
Jolyne_24 分钟前
grid 实现完美的水平铺满、间隔一致的自适应布局
前端·css
西洼工作室28 分钟前
【解决导航栏字体图标渲染导致文本闪烁问题】采用腾讯视频的解决方案
前端·css·css3
WindrunnerMax36 分钟前
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
前端·架构·github
CodeSheep41 分钟前
宇树科技,改名了!
前端·后端·程序员
Hilaku1 小时前
为什么我们用了 Vite 还是构建慢?——真正的优化在这几步
前端·javascript·vite
XI锐真的烦1 小时前
横向对比npm和yarn
前端·npm·node.js
国家不保护废物1 小时前
🧩 React 组件化进阶:像乐高大师一样搭建你的应用世界!
前端·react.js·ai编程
TimelessHaze1 小时前
从"切图崽"到前端工程师:React 到底是个啥?🚀
前端·react.js·ai编程
站在风口的猪11081 小时前
《前端面试题:CSS的display属性》
前端·css·html·css3·html5