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;
相关推荐
仰望星空的小猴子11 分钟前
React18和React19新特性
前端
小码哥_常12 分钟前
Android新航标:Navigation 3为何成为变革先锋?
前端
SuperEugene13 分钟前
Vue状态管理扫盲篇:状态管理中的常见坑 | 循环依赖、状态污染与调试技巧
前端·vue.js·面试
骑着小黑马14 分钟前
从 Electron 到 Tauri 2:我用 3.5MB 做了个音乐播放器
前端·vue.js·typescript
aykon14 分钟前
DataSource详解以及优势
前端
Mintopia15 分钟前
戴了 30 天智能手环后,我才发现自己一直低估了“睡眠”
前端
leolee1815 分钟前
react redux 简单使用
前端·react.js·redux
仰望星空的小猴子16 分钟前
常用的Hooks
前端
天才熊猫君16 分钟前
Vue Fragment 锚点机制
前端
米丘17 分钟前
Git 常用操作命令
前端