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);
}
相关推荐
清岚_lxn1 小时前
原生SSE实现AI智能问答+Vue3前端打字机流效果
前端·javascript·人工智能·vue·ai问答
ZoeLandia1 小时前
Element UI 设置 el-table-column 宽度 width 为百分比无效
前端·ui·element-ui
橘子味的冰淇淋~2 小时前
解决 vite.config.ts 引入scss 预处理报错
前端·vue·scss
小小小小宇4 小时前
V8 引擎垃圾回收机制详解
前端
lauo4 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
拉不动的猪4 小时前
设计模式之------单例模式
前端·javascript·面试
一袋米扛几楼985 小时前
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
前端·react.js·前端框架
Alt.95 小时前
SpringMVC基础二(RestFul、接收数据、视图跳转)
java·开发语言·前端·mvc
进取星辰5 小时前
1、从零搭建魔法工坊:React 19 新手村生存指南
前端·react.js·前端框架
前端开发张小七6 小时前
每日一练:2.leetcode回文数
前端·python