webpack 模块图 第 五 节


  • 依赖缓存机制

    • dependencyCacheProvide(dependency, ...args)

      • 提供依赖级的缓存计算功能,优先使用模块级缓存,其次使用全局缓存。
  • 兼容旧版 API 的方法(Webpack 6 中将被移除)

    • static getModuleGraphForModule(module, deprecateMessage, deprecationCode)

      • 获取指定模块对应的 ModuleGraph,带有弃用提示。
    • static setModuleGraphForModule(module, moduleGraph)

      • 设置模块与 ModuleGraph 的关联,用于兼容旧逻辑。
    • static clearModuleGraphForModule(module)

      • 清除模块与 ModuleGraph 的映射。
  • 内部数据结构

    • moduleGraphForModuleMap

      • WeakMap<Module, ModuleGraph>:用于旧 API 维护模块和模块图的映射关系。
    • deprecateMap

      • Map<string, (module) => ModuleGraph>:缓存已创建的弃用函数,避免重复生成。
  • 导出

    • 导出 ModuleGraph 类。
    • 同时导出 ModuleGraphConnection(用于表示模块间连接关系,代码中未展示)。
js 复制代码
class ModuleGraph {

	/**
	 * 为指定的依赖提供缓存机制。
	 * 如果已经有缓存的结果就直接返回,
	 * 否则执行传入的计算函数并缓存其返回值。
	 *
	 * @param {Dependency} dependency 依赖对象
	 * @param {...any} args 额外参数,最后一个是函数:fn(moduleGraph, dependency, ...args)
	 * @returns {any} 计算值或缓存值
	 */
	dependencyCacheProvide(dependency, ...args) {
		const fn = args.pop(); // 取出最后一个参数(实际用于计算的函数)
		if (this._moduleMemCaches && this._cacheStage) {
			// 从模块级内存缓存中尝试获取
			const memCache = this._moduleMemCaches.get(
				/** @type {Module} */ (this.getParentModule(dependency))
			);
			if (memCache !== undefined) {
				return memCache.provide(dependency, this._cacheStage, ...args, () =>
					fn(this, dependency, ...args)
				);
			}
		}
		// 若未启用缓存机制,则直接调用函数
		if (this._cache === undefined) return fn(this, dependency, ...args);
		// 否则使用通用缓存机制
		return this._cache.provide(dependency, ...args, () =>
			fn(this, dependency, ...args)
		);
	}

	// 以下三个方法为旧 API 的兼容支持,Webpack 6 将会移除

	/**
	 * (⚠️兼容方法)获取某个模块关联的 ModuleGraph 实例。
	 * 若首次调用则创建弃用警告函数并存入 Map。
	 *
	 * @param {Module} module 模块对象
	 * @param {string} deprecateMessage 弃用提示信息
	 * @param {string} deprecationCode 弃用代码标识
	 * @returns {ModuleGraph} 对应的模块图实例
	 */
	static getModuleGraphForModule(module, deprecateMessage, deprecationCode) {
		const fn = deprecateMap.get(deprecateMessage);
		if (fn) return fn(module);
		const newFn = util.deprecate(
			module => {
				const moduleGraph = moduleGraphForModuleMap.get(module);
				if (!moduleGraph)
					throw new Error(
						`${deprecateMessage}There was no ModuleGraph assigned to the Module for backward-compat (Use the new API)`
					);
				return moduleGraph;
			},
			`${deprecateMessage}: Use new ModuleGraph API`,
			deprecationCode
		);
		deprecateMap.set(deprecateMessage, newFn);
		return newFn(module);
	}

	/**
	 * (⚠️兼容方法)为模块设置 ModuleGraph 映射。
	 *
	 * @param {Module} module 模块对象
	 * @param {ModuleGraph} moduleGraph 模块图对象
	 */
	static setModuleGraphForModule(module, moduleGraph) {
		moduleGraphForModuleMap.set(module, moduleGraph);
	}

	/**
	 * (⚠️兼容方法)清除模块与 ModuleGraph 的映射。
	 *
	 * @param {Module} module 模块对象
	 */
	static clearModuleGraphForModule(module) {
		moduleGraphForModuleMap.delete(module);
	}
}

// 以下为旧 API 支持数据结构(Webpack 6 将移除)

/** 模块到 ModuleGraph 的映射表(用于旧 API) */
const moduleGraphForModuleMap = new WeakMap();

/** 弃用警告函数映射表(deprecateMessage -> fn) */
const deprecateMap = new Map();

module.exports = ModuleGraph;
module.exports.ModuleGraphConnection = ModuleGraphConnection;
相关推荐
憧憬成为web高手4 小时前
ACTF 12307复现
前端·bootstrap·html
wordbaby5 小时前
Axios 上传大文件崩溃:鸿蒙 RNOH 下 XHR 返回空响应头引发的"假失败"
前端·react native
wordbaby5 小时前
React Native 列表分页实战:下拉刷新与上拉加载的工程化方案
前端·react native
wordbaby6 小时前
脱离 Tab 栏的艺术:React Native 全屏子页面的导航架构实践
前端·react native·harmonyos
陈随易6 小时前
Redis 8.8发布,一定要更新
前端·后端·程序员
wordbaby7 小时前
React Native 新架构落地鸿蒙:跨三端政务级应用的工程实践与深度复盘
前端·react native·harmonyos
excel8 小时前
为什么我推荐使用 Termius:现代 SSH 工具的完整体验
前端·后端
ZC跨境爬虫8 小时前
模块化烹饪小程序开发日记 Day7:(菜谱详情接口开发与JSON数据读取全流程)
前端·javascript·css·ui·微信小程序·json
এ慕ོ冬℘゜8 小时前
JS 前端基础面试题
开发语言·前端·javascript
LaughingZhu8 小时前
Product Hunt 每日热榜 | 2026-05-25
前端·人工智能·经验分享·chatgpt·html