这部分 Module
类代码是 Webpack 构建系统中的"模块描述对象"功能实现核心,负责模块与 chunk 的关联管理、导出分析、依赖注册与清理等关键任务,支撑了模块图和 chunk 图构建、代码生成等多个构建阶段的基础逻辑。
js
/**
* 判断当前模块是否是入口模块(entry module)
* @returns {boolean}
*/
isEntryModule() {
return ChunkGraph.getChunkGraphForModule(
this,
"Module.isEntryModule",
"DEP_WEBPACK_MODULE_IS_ENTRY_MODULE"
).isEntryModule(this);
}
/**
* 获取当前模块所属的所有 chunk 列表
* @returns {Chunk[]}
*/
getChunks() {
return ChunkGraph.getChunkGraphForModule(
this,
"Module.getChunks",
"DEP_WEBPACK_MODULE_GET_CHUNKS"
).getModuleChunks(this);
}
/**
* 获取当前模块被包含在多少个 chunk 中
* @returns {number}
*/
getNumberOfChunks() {
return ChunkGraph.getChunkGraphForModule(
this,
"Module.getNumberOfChunks",
"DEP_WEBPACK_MODULE_GET_NUMBER_OF_CHUNKS"
).getNumberOfModuleChunks(this);
}
/**
* 获取当前模块所属 chunk 的有序可迭代对象(按 chunk id 排序)
* @returns {Iterable<Chunk>}
*/
get chunksIterable() {
return ChunkGraph.getChunkGraphForModule(
this,
"Module.chunksIterable",
"DEP_WEBPACK_MODULE_CHUNKS_ITERABLE"
).getOrderedModuleChunksIterable(this, compareChunksById);
}
/**
* 判断模块是否提供了指定的导出(export)
* @param {string} exportName - 要检查的导出名称
* @returns {boolean | null}
* - true: 提供了该导出;
* - false: 没有提供;
* - null: 无法确定(如模块尚未构建)
*/
isProvided(exportName) {
return ModuleGraph.getModuleGraphForModule(
this,
"Module.usedExports",
"DEP_WEBPACK_MODULE_USED_EXPORTS"
).isExportProvided(this, exportName);
}
/**
* 获取模块生成代码时使用的 exports 参数名
* @returns {string}
*/
get exportsArgument() {
return (this.buildInfo && this.buildInfo.exportsArgument) || "exports";
}
/**
* 获取模块生成代码时使用的 module 参数名
* @returns {string}
*/
get moduleArgument() {
return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
}
/**
* 获取模块的导出类型,用于生成 namespace 时的判断逻辑
* @param {ModuleGraph} moduleGraph - 模块图
* @param {boolean | undefined} strict - 是否启用严格模式(importing 模块是否为 strict)
* @returns {"namespace" | "default-only" | "default-with-named" | "dynamic"} 模块导出类型
*/
getExportsType(moduleGraph, strict) {
switch (this.buildMeta && this.buildMeta.exportsType) {
case "flagged":
// __esModule 为 true,提供 default 与 named(严格模式) 或直接 namespace
return strict ? "default-with-named" : "namespace";
case "namespace":
return "namespace";
case "default":
switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
case "redirect":
return "default-with-named";
case "redirect-warn":
return strict ? "default-only" : "default-with-named";
default:
return "default-only";
}
case "dynamic": {
// 动态根据 __esModule 决定
if (strict) return "default-with-named";
const handleDefault = () => {
switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
case "redirect":
case "redirect-warn":
return "default-with-named";
default:
return "default-only";
}
};
const exportInfo = moduleGraph.getReadOnlyExportInfo(this, "__esModule");
if (exportInfo.provided === false) {
return handleDefault();
}
const target = exportInfo.getTarget(moduleGraph);
if (
!target ||
!target.export ||
target.export.length !== 1 ||
target.export[0] !== "__esModule"
) {
return "dynamic";
}
switch (
target.module.buildMeta &&
target.module.buildMeta.exportsType
) {
case "flagged":
case "namespace":
return "namespace";
case "default":
return handleDefault();
default:
return "dynamic";
}
}
default:
// 未知类型时默认动态判断
return strict ? "default-with-named" : "dynamic";
}
}
/**
* 添加一个仅用于展示(presentation)的依赖(不会影响模块图)
* @param {Dependency} presentationalDependency
*/
addPresentationalDependency(presentationalDependency) {
if (this.presentationalDependencies === undefined) {
this.presentationalDependencies = [];
}
this.presentationalDependencies.push(presentationalDependency);
}
/**
* 添加一个用于代码生成的依赖(同时也应作为普通依赖添加)
* @param {Dependency} codeGenerationDependency
*/
addCodeGenerationDependency(codeGenerationDependency) {
if (this.codeGenerationDependencies === undefined) {
this.codeGenerationDependencies = [];
}
this.codeGenerationDependencies.push(codeGenerationDependency);
}
/**
* 清空所有依赖和代码块,包括展示依赖和代码生成依赖
*/
clearDependenciesAndBlocks() {
if (this.presentationalDependencies !== undefined) {
this.presentationalDependencies.length = 0;
}
if (this.codeGenerationDependencies !== undefined) {
this.codeGenerationDependencies.length = 0;
}
super.clearDependenciesAndBlocks();
}