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;
	}
}
相关推荐
我不吃饼干3 小时前
在 React 中实现倒计时功能会有什么坑
前端·react.js
小小小小宇4 小时前
前端PerformanceObserver
前端
王者鳜錸4 小时前
PYTHON从入门到实践-18Django从零开始构建Web应用
前端·python·sqlite
拾光拾趣录4 小时前
ES6到HTTPS全链路连环拷问,99%人第3题就翻车?
前端·面试
haaaaaaarry5 小时前
Element Plus常见基础组件(二)
开发语言·前端·javascript
xyphf_和派孔明5 小时前
关于echarts的性能优化考虑
前端·性能优化·echarts
PyHaVolask5 小时前
HTML 表单进阶:用户体验优化与实战应用
前端·javascript·html·用户体验
A了LONE5 小时前
cv弹窗,退款确认弹窗
java·服务器·前端
AntBlack6 小时前
闲谈 :AI 生成视频哪家强 ,掘友们有没有推荐的工具?
前端·后端·aigc
花菜会噎住7 小时前
Vue3核心语法进阶(computed与监听)
前端·javascript·vue.js