webpack 模块 第 二 节

核心作用总结

  • 该类作为 Webpack 构建系统中模块表示的核心抽象,维护了从模块定义、构建信息、优化状态到 Chunk 映射等全生命周期数据。
  • 同时提供了与 ModuleGraphChunkGraph 的交互能力,是整个模块依赖图和输出资源图的核心支点。
  • 插件、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);
}
相关推荐
大道归简32 分钟前
自动化实现web端Google SignUp——selenium
前端·selenium·自动化
普通young man2 小时前
QT | 常用控件
开发语言·前端·qt
想不明白的过度思考者2 小时前
为了结合后端而学习前端的学习日志——【黑洞光标特效】
前端·学习
twodragon&primy2 小时前
CSS布局
开发语言·前端·css·算法·html5
爱写代码的小朋友2 小时前
HTML与CSS实现风车旋转图形的代码技术详解
前端·css·html
程序员Bears2 小时前
深入理解现代JavaScript:从ES6+语法到Fetch API
前端·javascript·python·es6
IoOozZzzz3 小时前
ES6-Set-Map对象小记
前端·javascript·es6
浪裡遊3 小时前
利用flask设计接口
前端·后端·python·flask·web3.py·httpx
松树戈3 小时前
idea结合CopilotChat进行样式调整实践
前端·javascript·vue.js·copilot
溟洵4 小时前
【C++ Qt】输入类控件(上) LineEdit、QTextEdit
c语言·前端·c++·qt·前端框架