webpack 模块图 第 一 节

这段代码是 Webpack 模块图构建系统 的重要组成部分,ModuleGraphModule 是每个模块在图中的状态容器,而两个工具函数是为了高效分类模块之间的连接关系,为优化(如 Tree Shaking)和构建性能分析打基础。

ModuleGraphModule 类主要属性说明

  • incomingConnections

    • 类型:SortableSet<ModuleGraphConnection>
    • 说明:当前模块的入边连接(谁依赖了我)
  • outgoingConnections

    • 类型:SortableSet<ModuleGraphConnection> | undefined
    • 说明:当前模块的出边连接(我依赖了谁)
  • issuer

    • 类型:Module | null | undefined
    • 说明:引入该模块的模块(谁把我 import 了)
  • optimizationBailout

    • 类型:(string | OptimizationBailoutFunction)[]
    • 说明:记录该模块未被优化的原因(如 Tree Shaking 无效)
  • exports

    • 类型:ExportsInfo
    • 说明:模块导出信息(支持 Tree Shaking 和导出分析)
  • preOrderIndex

    • 类型:number | null
    • 说明:图遍历时的前序编号(DFS 顺序)
  • postOrderIndex

    • 类型:number | null
    • 说明:图遍历时的后序编号(DFS 结束时标号)
  • depth

    • 类型:number | null
    • 说明:模块在依赖图中的深度(用于排序优化)
  • profile

    • 类型:ModuleProfile | undefined
    • 说明:构建模块时的性能分析信息
  • async

    • 类型:boolean
    • 说明:是否是异步模块(如 import() 引入)
  • _unassignedConnections

    • 类型:ModuleGraphConnection[] | undefined
    • 说明:尚未归类的连接(构建过程中使用)

工具函数说明

  • getConnectionsByOriginModule(set)

    • 输入参数:SortableSet<ModuleGraphConnection>
    • 返回值:Map<Module | undefined, ModuleGraphConnection[]>
    • 说明:按照连接的 originModule(来源模块)对连接集合进行分组
  • getConnectionsByModule(set)

    • 输入参数:SortableSet<ModuleGraphConnection>
    • 返回值:Map<Module | undefined, ModuleGraphConnection[]>
    • 说明:按照连接的 module(目标模块)对连接集合进行分组

    类型别名说明

  • IncomingConnections

    • 实际类型:SortableSet<ModuleGraphConnection>
    • 说明:模块的所有入连接集合(被谁依赖)
  • OutgoingConnections

    • 实际类型:SortableSet<ModuleGraphConnection>
    • 说明:模块的所有出连接集合(依赖了谁)
  • OptimizationBailoutFunction

    • 类型定义:一个返回字符串的函数,接收 RequestShortener
    • 说明:用于说明模块为什么无法优化(比如缺少静态依赖信息)
js 复制代码
/** 引入类型定义,用于类型提示(非实际导入,只用于注释) */
/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./ExportsInfo").ExportInfo} ExportInfo */
/** @typedef {import("./Module")} Module */
/** @typedef {import("./ModuleProfile")} ModuleProfile */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */

/**
 * 优化失败回调类型定义。
 * 返回一个字符串,用于提示为什么该模块未被优化。
 * 可用于 `optimizationBailout` 数组中的元素。
 *
 * @callback OptimizationBailoutFunction
 * @param {RequestShortener} requestShortener - 用于路径简化
 * @returns {string} 优化失败原因
 */

const EMPTY_SET = new Set(); // 空集合常量,可复用避免重复创建

/**
 * 工具函数:按连接的"来源模块"(originModule)将连接进行分组
 * 
 * @param {SortableSet<ModuleGraphConnection>} set - 输入的模块连接集合
 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>}
 *          返回以"来源模块"为 key、连接数组为 value 的 Map
 */
const getConnectionsByOriginModule = set => {
	const map = new Map();
	let lastModule = 0; // 缓存上一个处理的模块
	let lastList;

	for (const connection of set) {
		const { originModule } = connection;

		// 如果与上一个模块相同,直接向缓存的连接数组中添加
		if (lastModule === originModule) {
			(lastList).push(connection);
		} else {
			lastModule = originModule;
			const list = map.get(originModule);

			if (list !== undefined) {
				lastList = list;
				list.push(connection);
			} else {
				const list = [connection];
				lastList = list;
				map.set(originModule, list);
			}
		}
	}
	return map;
};

/**
 * 工具函数:按连接的"目标模块"(module)将连接进行分组
 * 
 * @param {SortableSet<ModuleGraphConnection>} set - 输入的模块连接集合
 * @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]>}
 *          返回以"目标模块"为 key、连接数组为 value 的 Map
 */
const getConnectionsByModule = set => {
	const map = new Map();
	let lastModule = 0;
	let lastList;

	for (const connection of set) {
		const { module } = connection;

		if (lastModule === module) {
			(lastList).push(connection);
		} else {
			lastModule = module;
			const list = map.get(module);

			if (list !== undefined) {
				lastList = list;
				list.push(connection);
			} else {
				const list = [connection];
				lastList = list;
				map.set(module, list);
			}
		}
	}
	return map;
};

/** 类型别名:模块图中"指向该模块的连接" */
 /** @typedef {SortableSet<ModuleGraphConnection>} IncomingConnections */

/** 类型别名:模块图中"从该模块出发的连接" */
 /** @typedef {SortableSet<ModuleGraphConnection>} OutgoingConnections */

/**
 * 表示模块图中某个模块的元信息(状态、连接、导出等)
 */
class ModuleGraphModule {
	constructor() {
		/** @type {IncomingConnections} 当前模块的入边连接(谁依赖我) */
		this.incomingConnections = new SortableSet();

		/** @type {OutgoingConnections | undefined} 当前模块的出边连接(我依赖谁) */
		this.outgoingConnections = undefined;

		/** @type {Module | null | undefined} 引入该模块的模块(issuer) */
		this.issuer = undefined;

		/** @type {(string | OptimizationBailoutFunction)[]} 记录为什么该模块无法被优化 */
		this.optimizationBailout = [];

		/** @type {ExportsInfo} 当前模块的导出信息(用于 Tree Shaking 等优化) */
		this.exports = new ExportsInfo();

		/** @type {number | null} 当前模块在图遍历中的"前序遍历索引" */
		this.preOrderIndex = null;

		/** @type {number | null} 当前模块在图遍历中的"后序遍历索引" */
		this.postOrderIndex = null;

		/** @type {number | null} 模块在依赖图中的深度(越深优先级越低) */
		this.depth = null;

		/** @type {ModuleProfile | undefined} 构建该模块时的性能分析数据 */
		this.profile = undefined;

		/** @type {boolean} 是否为异步模块(通过 import() 等方式引入) */
		this.async = false;

		/** @type {ModuleGraphConnection[] | undefined} 未分类连接(临时存储) */
		this._unassignedConnections = undefined;
	}
}
相关推荐
老坛00118 分钟前
2025决策延迟的椭圆算子分析:锐减协同工具的谱间隙优化
前端
老坛00119 分钟前
从记录到预测:2025新一代预算工具如何通过AI实现前瞻性资金管理
前端
今禾21 分钟前
" 当Base64遇上Blob,图像转换不再神秘,让你的网页瞬间变身魔法画布! "
前端·数据可视化
华科云商xiao徐26 分钟前
高性能小型爬虫语言与代码示例
前端·爬虫
十盒半价26 分钟前
深入理解 React useEffect:从基础到实战的全攻略
前端·react.js·trae
攀登的牵牛花27 分钟前
Electron+Vue+Python全栈项目打包实战指南
前端·electron·全栈
iccb101328 分钟前
我是如何实现在线客服系统的极致稳定性与安全性的
前端·javascript·后端
一大树28 分钟前
Vue3祖孙组件通信方法总结
前端·vue.js
不要进入那温驯的良夜30 分钟前
跨平台UI自动化-Appium
前端
海底火旺30 分钟前
以一个简单的React应用理解数据绑定的重要性
前端·css·react.js