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;
相关推荐
云水一下4 小时前
从零开始!VMware安装Fedora Workstation 44桌面系统完整教程
前端
小码哥_常6 小时前
安卓黑科技:实现多平台商品详情页一键跳转APP
前端
killerbasd6 小时前
还是迷茫 5.3
前端·react.js·前端框架
不会敲代码17 小时前
TCP/IP 与前端性能:从数据包到首次渲染的底层逻辑
前端·tcp/ip
kyriewen7 小时前
奥特曼借GPT-5.5干杯,而你的Copilot正按Token收钱
前端·github·openai
AC赳赳老秦7 小时前
投标合规提效:用 OpenClaw 实现标书 / 合同自动审核、关键词校验、格式优化,降低废标风险
开发语言·前端·python·eclipse·emacs·deepseek·openclaw
kyriewen7 小时前
代码写成一锅粥?3个设计模式让你的项目“起死回生”
前端·javascript·设计模式
千寻girling7 小时前
《 Git 详细教程 》
前端·后端·面试
之歆9 小时前
DAY08_CSS浮动与行内块布局实战指南(下)
前端·css
yqcoder9 小时前
CSS Position 全解析:5 种定位模式详解
前端·css