Skip to content

addModule

make阶段第二步做的事是通过addModule将创建好的module添加到moduleGraph当中,构建起dependencymodule之间的关系。

_addModule

_addModulemodule缓存并记录到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);
  });
}
_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,建立dependencymodule父module之间的关系。

javascript
for (let i = 0;i < dependencies.length;i++) {
  const dependency = dependencies[i];
  moduleGraph.setResolvedModule(
    connectOrigin ? originModule : null,
    dependency,
    module
  );
}
for (let i = 0;i < dependencies.length;i++) {
  const dependency = dependencies[i];
  moduleGraph.setResolvedModule(
    connectOrigin ? originModule : null,
    dependency,
    module
  );
}

这里的originModule指代的是引用该module的父module

ModuleGraphConnection

ModuleGraphConnection记录了originModulemoduledependency,相当于三者之间的一个连接。

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);
    }

    // ...
  }
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;
  }
}
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;
  }
}
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();
/** @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);
}
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;
}
setIssuerIfUnset(module, issuer) {
  const mgm = this._getModuleGraphModule(module);
  if (mgm.issuer === undefined) mgm.issuer = issuer;
}

总结

addModule主要任务是记录当前的module并缓存起来。另外会建立dependencymodule父module三者之间的关系,所有关系均可从moduleGraph中取出。