addModule
make阶段第二步做的事是通过addModule将创建好的module添加到moduleGraph当中,构建起dependency和module之间的关系。
_addModule
_addModule将module缓存并记录到compilation.modules和_modules当中。
javascript
_addModule(module, callback) {
const identifier = module.identifier();
const alreadyAddedModule = this._modules.get(identifier);
// 判断 module 是否已经被添加,如果已经添加了直接跳过
if (alreadyAddedModule) {
return callback(null, alreadyAddedModule);
}
// 缓存 module
this._modulesCache.get(identifier, null, (err, cacheModule) => {
// 记录 module
this._modules.set(identifier, module);
this.modules.add(module);
ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
callback(null, module);
});
}随后执行callback回调,遍历dependencies,建立dependency、module和父module之间的关系。
javascript
for (let i = 0;i < dependencies.length;i++) {
const dependency = dependencies[i];
moduleGraph.setResolvedModule(
connectOrigin ? originModule : null,
dependency,
module
);
}这里的originModule指代的是引用该module的父module。
ModuleGraphConnection
ModuleGraphConnection记录了originModule、module、dependency,相当于三者之间的一个连接。
javascript
class ModuleGraphConnection {
constructor(
originModule,
dependency,
module,
explanation,
weak = false,
condition = undefined
) {
this.originModule = originModule;
this.resolvedOriginModule = originModule;
this.dependency = dependency;
this.resolvedModule = module;
this.module = module;
this.weak = weak;
this.conditional = !!condition;
this._active = condition !== false;
this.condition = condition || undefined;
this.explanations = undefined;
if (explanation) {
this.explanations = new Set();
this.explanations.add(explanation);
}
// ...
}ModuleGraphDependency
ModuleGraphDependency对应于dependency,记录dependency的内容。
javascript
class ModuleGraphDependency {
constructor() {
this.connection = undefined;
this.parentModule = undefined;
this.parentBlock = undefined;
}
}ModuleGraphModule
ModuleGraphModule对应于module,记录module的内容。
javascript
class ModuleGraphModule {
constructor() {
// connections 集合
this.incomingConnections = new SortableSet();
// connections 集合
this.outgoingConnections = undefined;
// 指向 父 module
this.issuer = undefined;
this.optimizationBailout = [];
this.exports = new ExportsInfo();
this.preOrderIndex = null;
this.postOrderIndex = null;
this.depth = null;
this.profile = undefined;
this.async = false;
}
}其中,通过outgoingConnections可以判断该module引用了哪些外部module。而通过incomingConnections可以判断该模块被哪些外部模块引用。
ModuleGraph
ModuleGraph记录了所有的dependency/module/connection。
javascript
/** @type {Map<Dependency, ModuleGraphDependency>} */
this._dependencyMap = new Map();
/** @type {Map<Module, ModuleGraphModule>} */
this._moduleMap = new Map();
/** @type {Map<Module, Set<ModuleGraphConnection>>} */
this._originMap = new Map();并且通过setResolvedModule方法来记录一个关系:
javascript
setResolvedModule(originModule, dependency, module) {
// 创建一个 connection,记录关系
const connection = new ModuleGraphConnection(
originModule,
dependency,
module,
undefined,
dependency.weak,
dependency.getCondition(this)
);
// 获取/创建 moduleGraphDependency
const mgd = this._getModuleGraphDependency(dependency);
// 赋值connection
mgd.connection = connection;
// 获取当前 module 的 incomingConnections
const connections = this._getModuleGraphModule(module).incomingConnections;
// 记录 connection,如果同一个模块被多个模块引用
// 那么就有多个 connection,也就能够找到引用该模块的父模块
connections.add(connection);
// 获取父模块的 mgm
const mgm = this._getModuleGraphModule(originModule);
if (mgm.outgoingConnections === undefined) {
mgm.outgoingConnections = new Set();
}
// 在父模块中记录当前模块,这样父模块就知道引用了哪些子模块。
mgm.outgoingConnections.add(connection);
}最后还会通过setIssuerIfUnset方法,记录第一个使用了该模块的模块。
javascript
setIssuerIfUnset(module, issuer) {
const mgm = this._getModuleGraphModule(module);
if (mgm.issuer === undefined) mgm.issuer = issuer;
}总结
addModule主要任务是记录当前的module并缓存起来。另外会建立dependency、module、父module三者之间的关系,所有关系均可从moduleGraph中取出。
