webpack 核心编译器 九 节

reportDependencyErrorsAndWarnings(module, blocks)

  • 递归遍历 blocks,获取所有依赖 (dependencies) 的错误 (getErrors()) 和警告 (getWarnings())。
  • 发现问题时,将错误/警告包装成 ModuleDependencyError 或 ModuleDependencyWarning 并存入 this.errors 或 this.warnings,返回 true 表示存在问题。
js 复制代码
	/**
	 * 报告模块及其依赖块中的错误和警告。
	 * @param {Module} module 需要报告的模块
	 * @param {DependenciesBlock[]} blocks 需要报告的依赖块
	 * @returns {boolean} 如果存在警告或错误,则返回 true
	 */
	reportDependencyErrorsAndWarnings(module, blocks) {
		let hasProblems = false;
		for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
			const block = blocks[indexBlock];
			const dependencies = block.dependencies;

			for (let indexDep = 0; indexDep < dependencies.length; indexDep++) {
				const d = dependencies[indexDep];

				// 获取并报告警告
				const warnings = d.getWarnings(this.moduleGraph);
				if (warnings) {
					for (let indexWar = 0; indexWar < warnings.length; indexWar++) {
						const w = warnings[indexWar];

						const warning = new ModuleDependencyWarning(module, w, d.loc);
						this.warnings.push(warning);
						hasProblems = true;
					}
				}

				// 获取并报告错误
				const errors = d.getErrors(this.moduleGraph);
				if (errors) {
					for (let indexErr = 0; indexErr < errors.length; indexErr++) {
						const e = errors[indexErr];

						const error = new ModuleDependencyError(module, e, d.loc);
						this.errors.push(error);
						hasProblems = true;
					}
				}
			}

			// 递归处理子块
			if (this.reportDependencyErrorsAndWarnings(module, block.blocks))
				hasProblems = true;
		}
		return hasProblems;
	}

codeGeneration(callback)

  • 遍历 this.modules,根据模块的 runtime 生成代码哈希 (hash),创建 代码生成任务 (jobs)。
  • 任务交给 _runCodeGenerationJobs 处理。
js 复制代码
	/**
	 * 生成代码。
	 * @param {Callback} callback 回调函数
	 */
	codeGeneration(callback) {
		const { chunkGraph } = this;
		this.codeGenerationResults = new CodeGenerationResults(
			this.outputOptions.hashFunction
		);
		/** @type {CodeGenerationJobs} */
		const jobs = [];
		for (const module of this.modules) {
			const runtimes = chunkGraph.getModuleRuntimes(module);
			if (runtimes.size === 1) {
				for (const runtime of runtimes) {
					const hash = chunkGraph.getModuleHash(module, runtime);
					jobs.push({ module, hash, runtime, runtimes: [runtime] });
				}
			} else if (runtimes.size > 1) {
				/** @type {Map<string, { runtimes: RuntimeSpec[] }>} */
				const map = new Map();
				for (const runtime of runtimes) {
					const hash = chunkGraph.getModuleHash(module, runtime);
					const job = map.get(hash);
					if (job === undefined) {
						const newJob = { module, hash, runtime, runtimes: [runtime] };
						jobs.push(newJob);
						map.set(hash, newJob);
					} else {
						job.runtimes.push(runtime);
					}
				}
			}
		}

		this._runCodeGenerationJobs(jobs, callback);
	}

_runCodeGenerationJobs(jobs, callback)

  • 采用 并行异步任务 (asyncLib.eachLimit()) 执行代码生成,优化并行度 (this.options.parallelism)。
  • 处理代码依赖 (codeGenerationDependencies),防止 循环依赖问题,避免死锁。
  • 记录 缓存命中 和 实际生成 的模块数,优化构建性能。
  • 发生循环依赖时,抛出错误:
js 复制代码
	/**
	 * @private
	 * 执行代码生成任务。
	 * @param {CodeGenerationJobs} jobs 代码生成任务
	 * @param {Callback} callback 回调函数
	 * @returns {void}
	 */
	_runCodeGenerationJobs(jobs, callback) {
		if (jobs.length === 0) {
			return callback();
		}
		let statModulesFromCache = 0;
		let statModulesGenerated = 0;
		const { chunkGraph, moduleGraph, dependencyTemplates, runtimeTemplate } =
			this;
		const results = this.codeGenerationResults;
		/** @type {WebpackError[]} */
		const errors = [];
		/** @type {NotCodeGeneratedModules | undefined} */
		let notCodeGeneratedModules;
		const runIteration = () => {
			/** @type {CodeGenerationJobs} */
			let delayedJobs = [];
			let delayedModules = new Set();
			asyncLib.eachLimit(
				jobs,
				/** @type {number} */
				(this.options.parallelism),
				(job, callback) => {
					const { module } = job;
					const { codeGenerationDependencies } = module;
					if (
						codeGenerationDependencies !== undefined &&
						(notCodeGeneratedModules === undefined ||
							codeGenerationDependencies.some(dep => {
								const referencedModule = /** @type {Module} */ (
									moduleGraph.getModule(dep)
								);
								return /** @type {NotCodeGeneratedModules} */ (
									notCodeGeneratedModules
								).has(referencedModule);
							})
						)
					) {
						delayedJobs.push(job);
						delayedModules.add(module);
						return callback();
					}
					const { hash, runtime, runtimes } = job;
					this._codeGenerationModule(
						module,
						runtime,
						runtimes,
						hash,
						dependencyTemplates,
						chunkGraph,
						moduleGraph,
						runtimeTemplate,
						errors,
						results,
						(err, codeGenerated) => {
							if (codeGenerated) statModulesGenerated++;
							else statModulesFromCache++;
							callback(err);
						}
					);
				},
				err => {
					if (err) return callback(err);
					callback();
				}
			);
		};
		runIteration();
	}
相关推荐
陈随易8 分钟前
副业搞钱点子之独立开发
前端·后端·程序员
console.log('npc')18 分钟前
问题跟踪与知识沉淀:从任务到知识的闭环)
前端·javascript·人工智能
恋猫de小郭36 分钟前
最近 Android 有什么更新:Android Dev Summit 2026 技术解读
android·前端·flutter
计算机魔术师38 分钟前
Reddit 宣布转向以登录为主的体验,以应对 AI 搜索带来的流量下滑
前端
熊猫钓鱼>_>38 分钟前
上架审核常见驳回与隐私合规清单:过审前先自查这 8 条【鸿蒙心迹】
开发语言·前端·华为·华为云·harmonyos·openharmony·ai制作
missile11139 分钟前
# HDR 算法 ISP 通路客制化方案(G100 / mt6789)
java·前端·javascript
全栈陈序员1 小时前
【Python】基础语法入门(三十)—— Web 开发入门:用 Flask 搭建第一个网站
前端·python·flask
万少1 小时前
Harmony 7.0 这个skill帮你自动化操作AGC
前端·javascript·后端
小大宇1 小时前
Vue知识点-ElementPlus-02图标
前端·javascript·vue.js
简简单单就是我_hehe1 小时前
一次 ClickHouse 服务器磁盘告警的排查与修复实录
java·服务器·前端