🔁 模块连接管理
-
copyOutgoingModuleConnections(oldModule, newModule, filterConnection)
-
作用:将旧模块的所有出站连接(即它依赖的模块)复制到新模块中。
-
使用场景:模块替换(如 HMR)、模块克隆等。
-
关键点:
- 如果
oldModule === newModule
,不做处理。 - 支持使用
filterConnection
过滤要复制的连接。 - 会克隆
ModuleGraphConnection
对象并重新设定originModule
。 - 同时会更新目标模块的入站连接集合。
- 如果
-
-
getConnection(dependency)
-
作用 :获取某个依赖对象对应的连接(
ModuleGraphConnection
)。 -
细节:
- 优先查
_dependencyMap
缓存。 - 若未命中,则尝试从依赖所属模块的
_unassignedConnections
中恢复连接。 - 最终会缓存结果,无连接则缓存为
null
。
- 优先查
-
-
getResolvedModule(dependency)
- 作用 :获取某依赖最终解析出的模块(
resolvedModule
)。 - 依赖于 :
getConnection()
。
- 作用 :获取某依赖最终解析出的模块(
-
getModule(dependency)
- 作用 :获取依赖指向的目标模块(
connection.module
)。 - 依赖于 :
getConnection()
。
- 作用 :获取依赖指向的目标模块(
-
getOrigin(dependency)
- 作用 :获取发出该依赖的源模块(
connection.originModule
)。
- 作用 :获取发出该依赖的源模块(
-
getResolvedOrigin(dependency)
- 作用 :获取依赖解析后的源模块(
resolvedOriginModule
)。
- 作用 :获取依赖解析后的源模块(
-
getIncomingConnections(module)
- 作用:返回所有指向该模块的连接(谁引用了它)。
- 结果类型 :
Iterable<ModuleGraphConnection>
。
-
getOutgoingConnections(module)
- 作用:获取模块出站连接(它引用了谁)。
- 结果类型 :
Iterable<ModuleGraphConnection>
。 - 若未定义,返回空集合
EMPTY_SET
。
-
getIncomingConnectionsByOriginModule(module)
- 作用:将模块的入站连接按"来源模块"分组。
- 缓存结构 :
Map<Module | undefined | null, ModuleGraphConnection[]>
。
-
getOutgoingConnectionsByModule(module)
- 作用:将模块的出站连接按"目标模块"分组。
- 缓存结构 :
Map<Module | undefined, ModuleGraphConnection[]>
。
🧩 模块元信息管理
-
addExtraReason(module, explanation)
- 作用:给模块添加一个"虚拟连接"作为额外引用理由(例如:它是某种默认模块)。
- 效果 :创建一个
ModuleGraphConnection(null, null, module, explanation)
加入入站集合。
-
getProfile(module)
- 作用 :获取模块的性能分析信息(
ModuleProfile
)。 - 用途:用于分析构建时长、缓存情况等。
- 作用 :获取模块的性能分析信息(
-
setProfile(module, profile)
- 作用:设置模块的性能分析信息。
-
getIssuer(module)
- 作用:获取模块的"issuer",即最初将其引入的模块。
- 用途:用于确定模块链路、生成模块名等。
-
setIssuer(module, issuer)
- 作用:设置模块的 issuer。
-
setIssuerIfUnset(module, issuer)
- 作用:仅在尚未设置 issuer 时设置它,避免重复赋值。
-
getOptimizationBailout(module)
- 作用:获取模块的优化阻止信息。
- 返回值 :可能是
true
、字符串数组,解释为何模块未被优化。
-
getProvidedExports(module)
- 作用:获取模块提供的导出信息(比如哪些命名导出可用于 Tree-shaking)。
- 调用的是内部的
exports.getProvidedExports()
方法。
js
/**
* 拷贝旧模块的所有出站连接到新模块(可通过 filter 过滤)
* @param {Module} oldModule 原始模块
* @param {Module} newModule 新模块
* @param {function(ModuleGraphConnection): boolean} filterConnection 过滤函数,返回 true 表示需要拷贝
* @returns {void}
*/
copyOutgoingModuleConnections(oldModule, newModule, filterConnection) {
if (oldModule === newModule) return;
const oldMgm = this._getModuleGraphModule(oldModule);
const newMgm = this._getModuleGraphModule(newModule);
// 获取旧模块的出站连接
const oldConnections = oldMgm.outgoingConnections;
if (oldConnections !== undefined) {
// 初始化新模块的出站连接集合
if (newMgm.outgoingConnections === undefined) {
newMgm.outgoingConnections = new SortableSet();
}
const newConnections = newMgm.outgoingConnections;
// 遍历旧的连接,如果满足过滤条件则复制到新模块中
for (const connection of oldConnections) {
if (filterConnection(connection)) {
const newConnection = connection.clone(); // 克隆连接对象
newConnection.originModule = newModule; // 设置新的起源模块
newConnections.add(newConnection); // 添加到新模块的出站连接中
// 同时更新目标模块的入站连接
if (newConnection.module !== undefined) {
const otherMgm = this._getModuleGraphModule(newConnection.module);
otherMgm.incomingConnections.add(newConnection);
}
}
}
}
}
/**
* 为模块添加一个额外引用理由(解释为何该模块被包含)
* @param {Module} module 被引用的模块
* @param {string} explanation 解释文本
* @returns {void}
*/
addExtraReason(module, explanation) {
const connections = this._getModuleGraphModule(module).incomingConnections;
connections.add(new ModuleGraphConnection(null, null, module, explanation));
}
/**
* 获取某依赖所解析到的最终模块
* @param {Dependency} dependency 依赖对象
* @returns {Module | null} 解析出的模块,若无结果返回 null
*/
getResolvedModule(dependency) {
const connection = this.getConnection(dependency);
return connection !== undefined ? connection.resolvedModule : null;
}
/**
* 获取依赖对应的连接信息
* @param {Dependency} dependency 依赖对象
* @returns {ModuleGraphConnection | undefined} 返回连接对象或 undefined
*/
getConnection(dependency) {
const connection = this._dependencyMap.get(dependency);
if (connection === undefined) {
// 尝试从所属模块中查找未分配的连接
const module = this.getParentModule(dependency);
if (module !== undefined) {
const mgm = this._getModuleGraphModule(module);
if (mgm._unassignedConnections && mgm._unassignedConnections.length !== 0) {
let foundConnection;
for (const connection of mgm._unassignedConnections) {
this._dependencyMap.set(connection.dependency, connection);
if (connection.dependency === dependency)
foundConnection = connection;
}
mgm._unassignedConnections.length = 0;
if (foundConnection !== undefined) {
return foundConnection;
}
}
}
this._dependencyMap.set(dependency, null);
return;
}
return connection === null ? undefined : connection;
}
/**
* 获取某依赖所指向的目标模块(未解析)
* @param {Dependency} dependency 依赖对象
* @returns {Module | null} 模块对象或 null
*/
getModule(dependency) {
const connection = this.getConnection(dependency);
return connection !== undefined ? connection.module : null;
}
/**
* 获取依赖的来源模块
* @param {Dependency} dependency 依赖对象
* @returns {Module | null} 来源模块
*/
getOrigin(dependency) {
const connection = this.getConnection(dependency);
return connection !== undefined ? connection.originModule : null;
}
/**
* 获取依赖的"解析后"的来源模块
* @param {Dependency} dependency 依赖对象
* @returns {Module | null} 解析后的来源模块
*/
getResolvedOrigin(dependency) {
const connection = this.getConnection(dependency);
return connection !== undefined ? connection.resolvedOriginModule : null;
}
/**
* 获取指定模块的所有入站连接(被哪些模块引用)
* @param {Module} module 目标模块
* @returns {Iterable<ModuleGraphConnection>} 入站连接集合
*/
getIncomingConnections(module) {
const connections = this._getModuleGraphModule(module).incomingConnections;
return connections;
}
/**
* 获取指定模块的所有出站连接(引用了哪些模块)
* @param {Module} module 模块对象
* @returns {Iterable<ModuleGraphConnection>} 出站连接集合
*/
getOutgoingConnections(module) {
const connections = this._getModuleGraphModule(module).outgoingConnections;
return connections === undefined ? EMPTY_SET : connections;
}
/**
* 获取模块的所有入站连接,并按来源模块分组(用于分析引用来源)
* @param {Module} module 模块对象
* @returns {readonly Map<Module | undefined | null, readonly ModuleGraphConnection[]>} 分组后的入站连接
*/
getIncomingConnectionsByOriginModule(module) {
const connections = this._getModuleGraphModule(module).incomingConnections;
return connections.getFromUnorderedCache(getConnectionsByOriginModule);
}
/**
* 获取模块的出站连接,并按目标模块分组
* @param {Module} module 模块对象
* @returns {readonly Map<Module | undefined, readonly ModuleGraphConnection[]> | undefined} 分组后的出站连接
*/
getOutgoingConnectionsByModule(module) {
const connections = this._getModuleGraphModule(module).outgoingConnections;
return connections === undefined
? undefined
: connections.getFromUnorderedCache(getConnectionsByModule);
}
/**
* 获取模块的性能分析信息(构建时间等)
* @param {Module} module 模块对象
* @returns {ModuleProfile | undefined} 模块性能数据
*/
getProfile(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.profile;
}
/**
* 设置模块的性能分析信息
* @param {Module} module 模块对象
* @param {ModuleProfile | undefined} profile 要设置的性能信息
* @returns {void}
*/
setProfile(module, profile) {
const mgm = this._getModuleGraphModule(module);
mgm.profile = profile;
}
/**
* 获取模块的"issuer"(最初引入它的模块)
* @param {Module} module 模块对象
* @returns {Module | null | undefined} issuer 模块
*/
getIssuer(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.issuer;
}
/**
* 设置模块的 issuer(谁引入了该模块)
* @param {Module} module 模块对象
* @param {Module | null} issuer 引入该模块的模块
* @returns {void}
*/
setIssuer(module, issuer) {
const mgm = this._getModuleGraphModule(module);
mgm.issuer = issuer;
}
/**
* 如果尚未设置 issuer,则设置一个
* @param {Module} module 模块对象
* @param {Module | null} issuer 引入该模块的模块
* @returns {void}
*/
setIssuerIfUnset(module, issuer) {
const mgm = this._getModuleGraphModule(module);
if (mgm.issuer === undefined) mgm.issuer = issuer;
}
/**
* 获取模块的优化提示信息(比如为何未优化)
* @param {Module} module 模块对象
* @returns {(string | OptimizationBailoutFunction)[]} 优化提示信息数组
*/
getOptimizationBailout(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.optimizationBailout;
}
/**
* 获取模块的导出信息(用于 Tree-shaking)
* @param {Module} module 模块对象
* @returns {true | string[] | null} 提供的导出名称或 null / true
*/
getProvidedExports(module) {
const mgm = this._getModuleGraphModule(module);
return mgm.exports.getProvidedExports();
}