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;
	}
}
相关推荐
bloxed3 分钟前
vue+vite 减缓首屏加载压力和性能优化
前端·vue.js·性能优化
打野赵怀真15 分钟前
React Hooks 的优势和使用场景
前端·javascript
HaushoLin19 分钟前
ERR_PNPM_DLX_NO_BIN No binaries found in tailwindcss
前端·vue.js·css3·html5
Lafar20 分钟前
Widget 树和 Element 树和RenderObject树是一一 对应的吗
前端
小桥风满袖21 分钟前
炸裂,前端神级动效库合集
前端·css
匆叔22 分钟前
Tauri 桌面端开发
前端·vue.js
1_2_3_23 分钟前
react-antd-column-resize(让你的table列可以拖拽列宽)
前端
Lafar23 分钟前
Flutter和iOS混合开发
前端·面试
九龙湖兔兔23 分钟前
pnpm给插件(naiveUI)打补丁
前端·架构