webpack 模块 第 二 节

核心作用总结

  • 该类作为 Webpack 构建系统中模块表示的核心抽象,维护了从模块定义、构建信息、优化状态到 Chunk 映射等全生命周期数据。
  • 同时提供了与 ModuleGraph 和 ChunkGraph 的交互能力,是整个模块依赖图和输出资源图的核心支点。
  • 插件、loader、优化器等都通过这个类实例获取模块相关信息或注入新信息。
js 复制代码
/**
 * Module 构造函数 - Webpack 中所有模块的基类
 * 提供模块的核心信息(类型、上下文、层、状态等)以及与模块图(ModuleGraph)和块图(ChunkGraph)的交互逻辑
 * 
 * @param {ModuleTypes | ""} type 模块类型,例如 'javascript/auto',当反序列化时类型未知为 ""
 * @param {(string | null)=} context 模块所在的上下文路径(通常是模块的目录)
 * @param {(string | null)=} layer 可选的 layer 分层(Webpack 支持根据层级进行优化)
 */
constructor(type, context = null, layer = null) {
	super();

	/** 模块类型(如 'javascript/auto') */
	this.type = type;
	/** 模块上下文路径 */
	this.context = context;
	/** 模块所属的层级(可用于分层构建) */
	this.layer = layer;
	/** 是否需要生成模块 ID(初始为 true) */
	this.needId = true;

	// 为每个模块生成唯一的调试 ID(自增)
	this.debugId = debugId++;

	// ===== Factory 构建阶段填充的信息 =====

	/** 模块的解析选项(resolve 配置) */
	this.resolveOptions = EMPTY_RESOLVE_OPTIONS;

	/** Factory 提供的元数据(可用于 loader、plugin 注入信息) */
	this.factoryMeta = undefined;

	/** 是否启用 SourceMap */
	this.useSourceMap = false;

	/** 是否启用简化版 SourceMap */
	this.useSimpleSourceMap = false;

	// ===== 是否处于 HMR 热更新环境 =====

	this.hot = false;

	// ===== 构建过程中填充的信息 =====

	/** 构建警告 */
	this._warnings = undefined;

	/** 构建错误 */
	this._errors = undefined;

	/** 构建时收集的元数据(如 harmonyExports、sideEffects) */
	this.buildMeta = undefined;

	/** 构建时收集的额外信息(如是否为 esm、cacheable 等) */
	this.buildInfo = undefined;

	/** 用于生成最终输出的呈现依赖 */
	this.presentationalDependencies = undefined;

	/** 用于生成代码的依赖集合 */
	this.codeGenerationDependencies = undefined;
}

// ===============================
// 以下为模块属性的访问器(getter/setter)
// ===============================

/**
 * 模块的唯一 ID(从 ChunkGraph 获取)
 * @returns {ModuleId | null}
 */
get id() {
	return ChunkGraph.getChunkGraphForModule(this, "Module.id", "DEP_WEBPACK_MODULE_ID").getModuleId(this);
}

/**
 * 设置模块 ID,如果是空字符串表示不需要 ID
 * @param {ModuleId} value
 */
set id(value) {
	if (value === "") {
		this.needId = false;
		return;
	}
	ChunkGraph.getChunkGraphForModule(this, "Module.id", "DEP_WEBPACK_MODULE_ID").setModuleId(this, value);
}

/**
 * 获取模块的 hash(唯一标识,通常由内容生成)
 * @returns {string}
 */
get hash() {
	return ChunkGraph.getChunkGraphForModule(this, "Module.hash", "DEP_WEBPACK_MODULE_HASH").getModuleHash(this, undefined);
}

/**
 * 获取模块的简短 hash(用于输出文件名)
 * @returns {string}
 */
get renderedHash() {
	return ChunkGraph.getChunkGraphForModule(this, "Module.renderedHash", "DEP_WEBPACK_MODULE_RENDERED_HASH").getRenderedModuleHash(this, undefined);
}

/**
 * 获取模块构建性能分析数据(profile)
 */
get profile() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.profile", "DEP_WEBPACK_MODULE_PROFILE").getProfile(this);
}

set profile(value) {
	ModuleGraph.getModuleGraphForModule(this, "Module.profile", "DEP_WEBPACK_MODULE_PROFILE").setProfile(this, value);
}

/**
 * 获取模块在模块图中的先序遍历索引
 * @returns {number | null}
 */
get index() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.index", "DEP_WEBPACK_MODULE_INDEX").getPreOrderIndex(this);
}

set index(value) {
	ModuleGraph.getModuleGraphForModule(this, "Module.index", "DEP_WEBPACK_MODULE_INDEX").setPreOrderIndex(this, value);
}

/**
 * 获取模块在模块图中的后序遍历索引
 * @returns {number | null}
 */
get index2() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.index2", "DEP_WEBPACK_MODULE_INDEX2").getPostOrderIndex(this);
}

set index2(value) {
	ModuleGraph.getModuleGraphForModule(this, "Module.index2", "DEP_WEBPACK_MODULE_INDEX2").setPostOrderIndex(this, value);
}

/**
 * 获取模块的深度(距离入口的距离)
 * @returns {number | null}
 */
get depth() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.depth", "DEP_WEBPACK_MODULE_DEPTH").getDepth(this);
}

set depth(value) {
	ModuleGraph.getModuleGraphForModule(this, "Module.depth", "DEP_WEBPACK_MODULE_DEPTH").setDepth(this, value);
}

/**
 * 获取引入当前模块的上级模块(issuer)
 * @returns {Module | null | undefined}
 */
get issuer() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.issuer", "DEP_WEBPACK_MODULE_ISSUER").getIssuer(this);
}

set issuer(value) {
	ModuleGraph.getModuleGraphForModule(this, "Module.issuer", "DEP_WEBPACK_MODULE_ISSUER").setIssuer(this, value);
}

/**
 * 获取当前模块被使用的导出(用于 tree-shaking)
 */
get usedExports() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.usedExports", "DEP_WEBPACK_MODULE_USED_EXPORTS").getUsedExports(this, undefined);
}

/**
 * 获取优化失败的原因(例如:无法进行 scope-hoisting)
 * @deprecated
 * @returns {(string | OptimizationBailoutFunction)[]}
 */
get optimizationBailout() {
	return ModuleGraph.getModuleGraphForModule(this, "Module.optimizationBailout", "DEP_WEBPACK_MODULE_OPTIMIZATION_BAILOUT").getOptimizationBailout(this);
}

/**
 * 当前模块是否为可选模块(一般用于动态 import 或异步模块)
 */
get optional() {
	return this.isOptional(ModuleGraph.getModuleGraphForModule(this, "Module.optional", "DEP_WEBPACK_MODULE_OPTIONAL"));
}

// ===============================
// ChunkGraph 操作(模块与 Chunk 的关系)
// ===============================

/**
 * 将模块添加到某个 chunk 中
 * @param {Chunk} chunk
 * @returns {boolean} 如果模块原本不在 chunk 中,则添加并返回 true;否则返回 false
 */
addChunk(chunk) {
	const chunkGraph = ChunkGraph.getChunkGraphForModule(this, "Module.addChunk", "DEP_WEBPACK_MODULE_ADD_CHUNK");
	if (chunkGraph.isModuleInChunk(this, chunk)) return false;
	chunkGraph.connectChunkAndModule(chunk, this);
	return true;
}

/**
 * 将模块从某个 chunk 中移除
 * @param {Chunk} chunk
 */
removeChunk(chunk) {
	return ChunkGraph.getChunkGraphForModule(this, "Module.removeChunk", "DEP_WEBPACK_MODULE_REMOVE_CHUNK").disconnectChunkAndModule(chunk, this);
}

/**
 * 判断模块是否属于某个 chunk
 * @param {Chunk} chunk
 * @returns {boolean}
 */
isInChunk(chunk) {
	return ChunkGraph.getChunkGraphForModule(this, "Module.isInChunk", "DEP_WEBPACK_MODULE_IS_IN_CHUNK").isModuleInChunk(this, chunk);
}
相关推荐
架构技术专栏6 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
别动我齐刘海7 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
志尊宝7 小时前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
刘发财8 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起0078 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户11481867894849 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界9 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队9 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一9 小时前
优化修整算法
前端·javascript·算法
weifont10 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化