webpack 核心编译器 第二节

这一节中主要对编译器新建时的执行流程做了一些,对构子部分的汪册以及对资源的处理。

js 复制代码
	constructor(compiler, params) {
		// 兼容模式的标志,继承自 compiler
		this._backCompat = compiler._backCompat;

		// 获取 NormalModuleLoader(已废弃)
		const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);

		/** 
		 * @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions
		 * 这里定义了 `processAssetsHook` 可能使用的额外选项:
		 * - `additionalAssets` 可选,值可以是 `true` 或一个函数:
		 *   - `true`:表示所有资产都需要额外处理
		 *   - `Function`:自定义的额外处理逻辑
		 */

		/** 
		 * 这里定义了一个异步的 `processAssetsHook` 钩子,
		 * 它是 AsyncSeriesHook(异步串行钩子),用于处理 `assets` 资源
		 */
		const processAssetsHook = new AsyncSeriesHook(["assets"]);

		// 用于存储已经处理过的 `assets` 文件
		let savedAssets = new Set();

		/**
		 * @param {CompilationAssets} assets 现有的 `assets` 资源
		 * @returns {CompilationAssets} 返回新增加的 `assets` 资源
		 *
		 * 这个函数的作用是找出 `assets` 中新增的资源,
		 * 避免重复处理已经存在的资源,并返回新资产的对象。
		 */
		const popNewAssets = assets => {
			let newAssets;
			for (const file of Object.keys(assets)) {
				// 如果该资源已经存在于 `savedAssets`,则跳过
				if (savedAssets.has(file)) continue;
				// 初始化 `newAssets` 为空对象
				if (newAssets === undefined) {
					newAssets = Object.create(null);
				}
				// 记录新增资源
				newAssets[file] = assets[file];
				// 将该资源加入 `savedAssets`
				savedAssets.add(file);
			}
			return newAssets;
		};

		// 拦截 `processAssetsHook` 的调用过程
		processAssetsHook.intercept({
			name: "Compilation",

			// 在 `call` 事件发生时,记录当前 `assets` 的状态
			call: () => {
				savedAssets = new Set(Object.keys(this.assets));
			},

			// 拦截 `register` 事件,修改注册的 `tap` 函数
			register: tap => {
				const { type, name } = tap;
				const { fn, additionalAssets, ...remainingTap } = tap;

				// 处理 `additionalAssets` 选项:
				// 如果是 `true`,使用原 `fn` 作为 `additionalAssetsFn`
				// 如果是函数,则直接使用该函数
				const additionalAssetsFn =
					additionalAssets === true ? fn : additionalAssets;

				// 记录已处理的 `assets`,防止重复处理
				const processedAssets = additionalAssetsFn ? new WeakSet() : undefined;

				// 根据 `type` 处理不同类型的 `tap`
				switch (type) {
					case "sync": // 同步钩子
						if (additionalAssetsFn) {
							// 注册 `processAdditionalAssets` 钩子
							this.hooks.processAdditionalAssets.tap(name, assets => {
								if (processedAssets.has(this.assets)) {
									additionalAssetsFn(assets);
								}
							});
						}
						// 将 `sync` 方式转换为 `async`
						return {
							...remainingTap,
							type: "async",
							fn: (assets, callback) => {
								try {
									fn(assets);
								} catch (err) {
									return callback(err);
								}
								if (processedAssets !== undefined)
									processedAssets.add(this.assets);
								const newAssets = popNewAssets(assets);
								if (newAssets !== undefined) {
									this.hooks.processAdditionalAssets.callAsync(
										newAssets,
										callback
									);
									return;
								}
								callback();
							}
						};

					case "async": // 异步钩子
						if (additionalAssetsFn) {
							// 注册 `processAdditionalAssets` 异步钩子
							this.hooks.processAdditionalAssets.tapAsync(
								name,
								(assets, callback) => {
									if (processedAssets.has(this.assets))
										return additionalAssetsFn(assets, callback);
									callback();
								}
							);
						}
						return {
							...remainingTap,
							fn: (assets, callback) => {
								fn(assets, err => {
									if (err) return callback(err);
									if (processedAssets !== undefined)
										processedAssets.add(this.assets);
									const newAssets = popNewAssets(assets);
									if (newAssets !== undefined) {
										this.hooks.processAdditionalAssets.callAsync(
											newAssets,
											callback
										);
										return;
									}
									callback();
								});
							}
						};

					case "promise": // Promise 方式的钩子
						if (additionalAssetsFn) {
							// 注册 `processAdditionalAssets` 的 Promise 钩子
							this.hooks.processAdditionalAssets.tapPromise(name, assets => {
								if (processedAssets.has(this.assets))
									return additionalAssetsFn(assets);
								return Promise.resolve();
							});
						}
						return {
							...remainingTap,
							fn: assets => {
								const p = fn(assets);
								if (!p || !p.then) return p;
								return p.then(() => {
									if (processedAssets !== undefined)
										processedAssets.add(this.assets);
									const newAssets = popNewAssets(assets);
									if (newAssets !== undefined) {
										return this.hooks.processAdditionalAssets.promise(
											newAssets
										);
									}
								});
							}
						};
				}
			}
		});

		/** 
		 * @type {SyncHook<[CompilationAssets]>} 
		 * 定义一个同步钩子 `afterProcessAssetsHook`,用于在 `processAssetsHook` 之后执行额外的操作
		 */
		const afterProcessAssetsHook = new SyncHook(["assets"]);

		/**
		 * @template T
		 * @param {string} name hook 的名称
		 * @param {number} stage 该 hook 在 processAssetsHook 执行的阶段
		 * @param {function(): AsArray<T>} getArgs 获取旧 hook 需要的参数
		 * @param {string=} code 废弃代码的标识(如果未设置,则不认为是废弃)
		 * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>}
		 * 返回一个模拟的 `hook`,用于将老的 `hook` 重定向到 `processAssetsHook`
		 *
		 * 这个方法用于创建一个"虚拟的" `processAssetsHook`,使得旧的钩子 API 仍然可以使用,
		 * 但实际上它们会被引导到 `processAssetsHook`,以保持 Webpack 5 兼容 Webpack 4。
		 */
		const createProcessAssetsHook = (name, stage, getArgs, code) => {
			// 如果不在兼容模式下,并且 `code` 存在(表示该 API 被废弃),则直接返回,不创建 hook
			if (!this._backCompat && code) return;

			/**
			 * 生成错误信息的函数
			 * @param {string} reason 失败的原因
			 * @returns {string} 返回错误信息
			 *
			 * 这个函数用于提示用户,Webpack 5 统一了 `processAssets` 相关的 hooks,导致旧的 hooks 不能直接使用。
			 */
			const errorMessage =
				reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;

			/**
			 * 解析 `options` 并附加 `stage` 参数
			 * @param {Object|string} options 传入的 tap 选项,可以是字符串或对象
			 * @returns {Object} 返回带 `stage` 选项的新对象
			 *
			 * 这个函数的作用是确保 `options` 格式正确,并且禁止用户手动指定 `stage`,
			 * 因为 `stage` 由 `createProcessAssetsHook` 统一管理。
			 */
			const getOptions = options => {
				if (typeof options === "string") options = { name: options };
				if (options.stage) {
					// 如果用户尝试指定 `stage`,则抛出错误
					throw new Error(errorMessage("it's using the 'stage' option"));
				}
				return { ...options, stage };
			};

			// 创建一个模拟的 `hook`,用于兼容 Webpack 4 的老 API
			return createFakeHook(
				{
					name,
					/** 
					 * @type {AsyncSeriesHook<T>["intercept"]} 
					 * 拦截 `intercept` 方法,直接抛出错误,提示用户该 API 不能被拦截。
					 */
					intercept(interceptor) {
						throw new Error(errorMessage("it's using 'intercept'"));
					},
					/** 
					 * @type {AsyncSeriesHook<T>["tap"]} 
					 * 处理 `tap` 方法,将其重定向到 `processAssetsHook.tap`
					 */
					tap: (options, fn) => {
						processAssetsHook.tap(getOptions(options), () => fn(...getArgs()));
					},
					/** 
					 * @type {AsyncSeriesHook<T>["tapAsync"]} 
					 * 处理 `tapAsync` 方法,将其重定向到 `processAssetsHook.tapAsync`
					 */
					tapAsync: (options, fn) => {
						processAssetsHook.tapAsync(
							getOptions(options),
							(assets, callback) =>
						/** @type {any} */(fn)(...getArgs(), callback)
						);
					},
					/** 
					 * @type {AsyncSeriesHook<T>["tapPromise"]} 
					 * 处理 `tapPromise` 方法,将其重定向到 `processAssetsHook.tapPromise`
					 */
					tapPromise: (options, fn) => {
						processAssetsHook.tapPromise(getOptions(options), () =>
							fn(...getArgs())
						);
					}
				},
				// 提示用户,该 `hook` 已被废弃,建议使用 `processAssetsHook` 并指定 `stage`
				`${name} is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)`,
				code
			);
		};

		this.hooks = Object.freeze({
			/** @type {SyncHook<[Module]>} */
			buildModule: new SyncHook(["module"]), // 构建模块的钩子

			/** @type {SyncHook<[Module]>} */
			rebuildModule: new SyncHook(["module"]), // 重新构建模块的钩子

			/** @type {SyncHook<[Module, WebpackError]>} */
			failedModule: new SyncHook(["module", "error"]), // 模块构建失败的钩子

			/** @type {SyncHook<[Module]>} */
			succeedModule: new SyncHook(["module"]), // 模块构建成功的钩子

			/** @type {SyncHook<[Module]>} */
			stillValidModule: new SyncHook(["module"]), // 模块仍然有效的钩子

			/** @type {SyncHook<[Dependency, EntryOptions]>} */
			addEntry: new SyncHook(["entry", "options"]), // 添加入口的钩子

			/** @type {SyncHook<[Dependency, EntryOptions, Error]>} */
			failedEntry: new SyncHook(["entry", "options", "error"]), // 入口添加失败的钩子

			/** @type {SyncHook<[Dependency, EntryOptions, Module]>} */
			succeedEntry: new SyncHook(["entry", "options", "module"]), // 入口添加成功的钩子

			/** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency, RuntimeSpec]>} */
			dependencyReferencedExports: new SyncWaterfallHook([
				"referencedExports", "dependency", "runtime"
			]), // 依赖项引用导出的钩子

			/** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
			executeModule: new SyncHook(["options", "context"]), // 执行模块的钩子

			/** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */
			prepareModuleExecution: new AsyncParallelHook(["options", "context"]), // 准备执行模块的钩子

			/** @type {AsyncSeriesHook<[Iterable<Module>]>} */
			finishModules: new AsyncSeriesHook(["modules"]), // 完成模块处理的钩子

			/** @type {AsyncSeriesHook<[Module]>} */
			finishRebuildingModule: new AsyncSeriesHook(["module"]), // 完成重新构建模块的钩子

			/** @type {SyncHook<[]>} */
			unseal: new SyncHook([]), // 解封的钩子

			/** @type {SyncHook<[]>} */
			seal: new SyncHook([]), // 密封的钩子

			/** @type {SyncHook<[]>} */
			beforeChunks: new SyncHook([]), // 在分块之前的钩子

			/** @type {SyncHook<[Iterable<Chunk>]>} */
			afterChunks: new SyncHook(["chunks"]), // 在分块之后的钩子

			/** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
			optimizeDependencies: new SyncBailHook(["modules"]), // 优化依赖项的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			afterOptimizeDependencies: new SyncHook(["modules"]), // 优化依赖项后的钩子

			/** @type {SyncHook<[]>} */
			optimize: new SyncHook([]), // 优化的钩子

			/** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
			optimizeModules: new SyncBailHook(["modules"]), // 优化模块的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			afterOptimizeModules: new SyncHook(["modules"]), // 优化模块后的钩子

			/** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]], boolean | void>} */
			optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]), // 优化分块的钩子

			/** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */
			afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]), // 优化分块后的钩子

			/** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */
			optimizeTree: new AsyncSeriesHook(["chunks", "modules"]), // 优化树形结构的钩子

			/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
			afterOptimizeTree: new SyncHook(["chunks", "modules"]), // 优化树形结构后的钩子

			/** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>], void>} */
			optimizeChunkModules: new AsyncSeriesBailHook(["chunks", "modules"]), // 优化分块模块的钩子

			/** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
			afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]), // 优化分块模块后的钩子

			/** @type {SyncBailHook<[], boolean | void>} */
			shouldRecord: new SyncBailHook([]), // 是否需要记录的钩子

			/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
			additionalChunkRuntimeRequirements: new SyncHook([
				"chunk", "runtimeRequirements", "context"
			]), // 额外分块的运行时需求的钩子

			/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */
			runtimeRequirementInChunk: new HookMap(
				() => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
			), // 在分块中运行时需求的钩子

			/** @type {SyncHook<[Module, Set<string>, RuntimeRequirementsContext]>} */
			additionalModuleRuntimeRequirements: new SyncHook([
				"module", "runtimeRequirements", "context"
			]), // 额外模块的运行时需求的钩子

			/** @type {HookMap<SyncBailHook<[Module, Set<string>, RuntimeRequirementsContext], void>>} */
			runtimeRequirementInModule: new HookMap(
				() => new SyncBailHook(["module", "runtimeRequirements", "context"])
			), // 在模块中运行时需求的钩子

			/** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */
			additionalTreeRuntimeRequirements: new SyncHook([
				"chunk", "runtimeRequirements", "context"
			]), // 额外树形结构的运行时需求的钩子

			/** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */
			runtimeRequirementInTree: new HookMap(
				() => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
			), // 在树形结构中运行时需求的钩子

			/** @type {SyncHook<[RuntimeModule, Chunk]>} */
			runtimeModule: new SyncHook(["module", "chunk"]), // 运行时模块的钩子

			/** @type {SyncHook<[Iterable<Module>, any]>} */
			reviveModules: new SyncHook(["modules", "records"]), // 恢复模块的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			beforeModuleIds: new SyncHook(["modules"]), // 在模块ID之前的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			moduleIds: new SyncHook(["modules"]), // 模块ID的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			optimizeModuleIds: new SyncHook(["modules"]), // 优化模块ID的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			afterOptimizeModuleIds: new SyncHook(["modules"]), // 优化模块ID后的钩子

			/** @type {SyncHook<[Iterable<Chunk>, any]>} */
			reviveChunks: new SyncHook(["chunks", "records"]), // 恢复分块的钩子

			/** @type {SyncHook<[Iterable<Chunk>]>} */
			beforeChunkIds: new SyncHook(["chunks"]), // 在分块ID之前的钩子

			/** @type {SyncHook<[Iterable<Chunk>]>} */
			chunkIds: new SyncHook(["chunks"]), // 分块ID的钩子

			/** @type {SyncHook<[Iterable<Chunk>]>} */
			optimizeChunkIds: new SyncHook(["chunks"]), // 优化分块ID的钩子

			/** @type {SyncHook<[Iterable<Chunk>]>} */
			afterOptimizeChunkIds: new SyncHook(["chunks"]), // 优化分块ID后的钩子

			/** @type {SyncHook<[Iterable<Module>, any]>} */
			recordModules: new SyncHook(["modules", "records"]), // 记录模块的钩子

			/** @type {SyncHook<[Iterable<Chunk>, any]>} */
			recordChunks: new SyncHook(["chunks", "records"]), // 记录分块的钩子

			/** @type {SyncHook<[Iterable<Module>]>} */
			optimizeCodeGeneration: new SyncHook(["modules"]), // 优化代码生成的钩子

			/** @type {SyncHook<[]>} */
			beforeModuleHash: new SyncHook([]), // 在模块哈希之前的钩子

			/** @type {SyncHook<[]>} */
			afterModuleHash: new SyncHook([]), // 模块哈希之后的钩子

			/** @type {SyncHook<[]>} */
			beforeCodeGeneration: new SyncHook([]), // 在代码生成之前的钩子

			/** @type {SyncHook<[]>} */
			afterCodeGeneration: new SyncHook([]), // 代码生成之后的钩子

			/** @type {SyncHook<[]>} */
			beforeRuntimeRequirements: new SyncHook([]), // 在运行时需求之前的钩子

			/** @type {SyncHook<[]>} */
			afterRuntimeRequirements: new SyncHook([]), // 运行时需求之后的钩子

			/** @type {SyncHook<[]>} */
			beforeHash: new SyncHook([]), // 在哈希之前的钩子

			/** @type {SyncHook<[Chunk]>} */
			contentHash: new SyncHook(["chunk"]), // 内容哈希的钩子

			/** @type {SyncHook<[]>} */
			afterHash: new SyncHook([]), // 哈希之后的钩子

			/** @type {SyncHook<[any]>} */
			recordHash: new SyncHook(["records"]), // 记录哈希的钩子

			/** @type {SyncHook<[Compilation, any]>} */
			record: new SyncHook(["compilation", "records"]), // 记录的钩子

			/** @type {SyncHook<[]>} */
			beforeModuleAssets: new SyncHook([]), // 在模块资产之前的钩子

			/** @type {SyncBailHook<[], boolean | void>} */
			shouldGenerateChunkAssets: new SyncBailHook([]), // 是否需要生成分块资产的钩子

			/** @type {SyncHook<[]>} */
			beforeChunkAssets: new SyncHook([]), // 在分块资产之前的钩子

			/** @deprecated */
			additionalChunkAssets: createProcessAssetsHook(
				"additionalChunkAssets",
				Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
				() => [this.chunks],
				"DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS"
			), // 额外分块资产的钩子(废弃)

			/** @deprecated */
			additionalAssets: createProcessAssetsHook(
				"additionalAssets",
				Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
				() => []
			), // 额外资产的钩子(废弃)

			/** @deprecated */
			optimizeChunkAssets: createProcessAssetsHook(
				"optimizeChunkAssets",
				Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
				() => [this.chunks],
				"DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS"
			), // 优化分块资产的钩子(废弃)

			/** @deprecated */
			afterOptimizeChunkAssets: createProcessAssetsHook(
				"afterOptimizeChunkAssets",
				Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1,
				() => [this.chunks],
				"DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS"
			), // 优化分块资产后的钩子(废弃)

			/** @deprecated */
			optimizeAssets: processAssetsHook, // 优化资产的钩子(废弃)

			/** @deprecated */
			afterOptimizeAssets: afterProcessAssetsHook, // 优化资产后的钩子(废弃)

			processAssets: processAssetsHook, // 处理资产的钩子

			afterProcessAssets: afterProcessAssetsHook, // 处理资产后的钩子

			/** @type {AsyncSeriesHook<[CompilationAssets]>} */
			processAdditionalAssets: new AsyncSeriesHook(["assets"]), // 处理额外资产的钩子

			/** @type {SyncBailHook<[], boolean | void>} */
			needAdditionalSeal: new SyncBailHook([]), // 是否需要额外密封的钩子

			/** @type {AsyncSeriesHook<[]>} */
			afterSeal: new AsyncSeriesHook([]), // 密封之后的钩子

			/** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
			renderManifest: new SyncWaterfallHook(["result", "options"]), // 渲染清单的钩子

			/** @type {SyncHook<[Hash]>} */
			fullHash: new SyncHook(["hash"]), // 完整哈希的钩子

			/** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */
			chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]), // 分块哈希的钩子

			/** @type {SyncHook<[Module, string]>} */
			moduleAsset: new SyncHook(["module", "filename"]), // 模块资产的钩子

			/** @type {SyncHook<[Chunk, string]>} */
			chunkAsset: new SyncHook(["chunk", "filename"]), // 分块资产的钩子

			/** @type {SyncWaterfallHook<[string, object, AssetInfo | undefined]>} */
			assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]), // 资产路径的钩子

			/** @type {SyncBailHook<[], boolean | void>} */
			needAdditionalPass: new SyncBailHook([]), // 是否需要额外通道的钩子

			/** @type {SyncHook<[Compiler, string, number]>} */
			childCompiler: new SyncHook([
				"childCompiler", "compilerName", "compilerIndex"
			]), // 子编译器的钩子

			/** @type {SyncBailHook<[string, LogEntry], boolean | void>} */
			log: new SyncBailHook(["origin", "logEntry"]), // 日志钩子

			/** @type {SyncWaterfallHook<[WebpackError[]]>} */
			processWarnings: new SyncWaterfallHook(["warnings"]), // 处理警告的钩子

			/** @type {SyncWaterfallHook<[WebpackError[]]>} */
			processErrors: new SyncWaterfallHook(["errors"]), // 处理错误的钩子

			/** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */
			statsPreset: new HookMap(() => new SyncHook(["options", "context"])), // 统计预设的钩子

			/** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */
			statsNormalize: new SyncHook(["options", "context"]), // 统计规范化的钩子

			/** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */
			statsFactory: new SyncHook(["statsFactory", "options"]), // 统计工厂的钩子

			/** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */
			statsPrinter: new SyncHook(["statsPrinter", "options"]), // 统计打印的钩子

			// 获取正常模块加载器
			get normalModuleLoader() {
				return getNormalModuleLoader();
			}
		});
		/** @type {string=} */
		this.name = undefined; // 编译的名称,默认为未定义

		/** @type {number | undefined} */
		this.startTime = undefined; // 编译开始时间,默认为未定义

		/** @type {number | undefined} */
		this.endTime = undefined; // 编译结束时间,默认为未定义

		/** @type {Compiler} */
		this.compiler = compiler; // 当前的编译器实例

		this.resolverFactory = compiler.resolverFactory; // 用于解析模块的工厂方法

		/** @type {InputFileSystem} */
		this.inputFileSystem = (compiler.inputFileSystem); // 文件系统接口,用于读取文件

		this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, {
			unmanagedPaths: compiler.unmanagedPaths, // 未管理的路径
			managedPaths: compiler.managedPaths, // 已管理的路径
			immutablePaths: compiler.immutablePaths, // 不可变的路径
			logger: this.getLogger("webpack.FileSystemInfo"), // 日志记录器
			hashFunction: compiler.options.output.hashFunction // 哈希函数,用于生成文件的哈希值
		});

		// 添加文件时间戳信息
		if (compiler.fileTimestamps) {
			this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
		}
		if (compiler.contextTimestamps) {
			this.fileSystemInfo.addContextTimestamps(compiler.contextTimestamps, true);
		}

		/** @type {ValueCacheVersions} */
		this.valueCacheVersions = new Map(); // 存储缓存的版本信息

		this.requestShortener = compiler.requestShortener; // 请求路径缩短器,用于简化路径显示

		this.compilerPath = compiler.compilerPath; // 编译器路径,用于路径解析

		this.logger = this.getLogger("webpack.Compilation"); // 编译过程的日志记录器

		const options = /** @type {WebpackOptions} */ (compiler.options);
		this.options = options; // 配置项

		this.outputOptions = options && options.output; // 输出配置项

		/** @type {boolean} */
		this.bail = (options && options.bail) || false; // 是否在遇到错误时中止编译

		/** @type {boolean} */
		this.profile = (options && options.profile) || false; // 是否启用性能分析

		this.params = params; // 传递的参数

		this.mainTemplate = new MainTemplate(this.outputOptions, this); // 主模板,用于生成输出文件

		this.chunkTemplate = new ChunkTemplate(this.outputOptions, this); // Chunk模板,用于生成模块拆分后的文件

		this.runtimeTemplate = new RuntimeTemplate(this, this.outputOptions, this.requestShortener); // 运行时模板,用于生成运行时代码

		/** @type {ModuleTemplates} */
		this.moduleTemplates = {
			javascript: new ModuleTemplate(this.runtimeTemplate, this) // JavaScript模块模板
		};
		defineRemovedModuleTemplates(this.moduleTemplates); // 定义已移除的模块模板

		/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
		this.moduleMemCaches = undefined; // 模块内存缓存,用于缓存模块状态

		/** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */
		this.moduleMemCaches2 = undefined; // 第二级模块内存缓存

		this.moduleGraph = new ModuleGraph(); // 模块图,用于追踪模块之间的依赖关系

		/** @type {ChunkGraph} */
		this.chunkGraph = undefined; // 块图,用于管理生成的块的关系

		/** @type {CodeGenerationResults} */
		this.codeGenerationResults = undefined; // 代码生成的结果

		/** @type {AsyncQueue<Module, Module, Module>} */
		this.processDependenciesQueue = new AsyncQueue({
			name: "processDependencies", // 队列名称
			parallelism: options.parallelism || 100, // 并行度
			processor: this._processModuleDependencies.bind(this) // 处理依赖的回调函数
		});

		/** @type {AsyncQueue<Module, string, Module>} */
		this.addModuleQueue = new AsyncQueue({
			name: "addModule", // 队列名称
			parent: this.processDependenciesQueue, // 父队列
			getKey: module => module.identifier(), // 获取模块的唯一标识符
			processor: this._addModule.bind(this) // 添加模块的回调函数
		});

		/** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
		this.factorizeQueue = new AsyncQueue({
			name: "factorize", // 队列名称
			parent: this.addModuleQueue, // 父队列
			processor: this._factorizeModule.bind(this) // 模块因式分解的回调函数
		});

		/** @type {AsyncQueue<Module, Module, Module>} */
		this.buildQueue = new AsyncQueue({
			name: "build", // 队列名称
			parent: this.factorizeQueue, // 父队列
			processor: this._buildModule.bind(this) // 构建模块的回调函数
		});

		/** @type {AsyncQueue<Module, Module, Module>} */
		this.rebuildQueue = new AsyncQueue({
			name: "rebuild", // 队列名称
			parallelism: options.parallelism || 100, // 并行度
			processor: this._rebuildModule.bind(this) // 重新构建模块的回调函数
		});

		/**
		 * 当前模块的值为正在构建的模块,表示这些模块正在阻塞其他模块的构建
		 * 用于检测构建中的循环依赖
		 * @type {WeakMap<Module, Set<Module>>}
		 */
		this.creatingModuleDuringBuild = new WeakMap(); // 记录构建中的模块依赖关系

		/** @type {Map<string, EntryData>} */
		this.entries = new Map(); // 存储入口配置

		/** @type {EntryData} */
		this.globalEntry = {
			dependencies: [], // 入口的依赖
			includeDependencies: [], // 包含的依赖
			options: {
				name: undefined // 入口名称
			}
		};
		/** @type {Map<string, Entrypoint>} */
		this.entrypoints = new Map(); // 存储入口点的映射,每个入口点对应一个模块的集合

		/** @type {Entrypoint[]} */
		this.asyncEntrypoints = []; // 异步入口点的数组,用于处理按需加载的模块

		/** @type {Set<Chunk>} */
		this.chunks = new Set(); // 存储生成的所有块(Chunk)

		/** @type {ChunkGroup[]} */
		this.chunkGroups = []; // 存储块组的数组,用于组织多个块的关系

		/** @type {Map<string, ChunkGroup>} */
		this.namedChunkGroups = new Map(); // 存储命名的块组

		/** @type {Map<string, Chunk>} */
		this.namedChunks = new Map(); // 存储命名的块

		/** @type {Set<Module>} */
		this.modules = new Set(); // 存储所有模块的集合

		// 兼容旧版本的处理
		if (this._backCompat) {
			arrayToSetDeprecation(this.chunks, "Compilation.chunks");
			arrayToSetDeprecation(this.modules, "Compilation.modules");
		}

		/**
		 * @private
		 * @type {Map<string, Module>}
		 */
		this._modules = new Map(); // 存储模块的私有映射

		this.records = null; // 编译记录,可能用于缓存或保存编译信息

		/** @type {string[]} */
		this.additionalChunkAssets = []; // 存储额外的块资产

		/** @type {CompilationAssets} */
		this.assets = {}; // 存储编译生成的资源文件

		/** @type {Map<string, AssetInfo>} */
		this.assetsInfo = new Map(); // 存储资产信息(如资源的哈希、大小等)

		/** @type {Map<string, Map<string, Set<string>>>} */
		this._assetsRelatedIn = new Map(); // 存储与资产相关联的映射,用于处理依赖关系

		/** @type {WebpackError[]} */
		this.errors = []; // 存储编译时的错误信息

		/** @type {WebpackError[]} */
		this.warnings = []; // 存储编译时的警告信息

		/** @type {Compilation[]} */
		this.children = []; // 存储子编译实例,用于支持多目标编译

		/** @type {Map<string, LogEntry[]>} */
		this.logging = new Map(); // 存储日志条目的映射

		/** @type {Map<DepConstructor, ModuleFactory>} */
		this.dependencyFactories = new Map(); // 存储依赖构造函数和模块工厂的映射,用于处理模块依赖

		/** @type {DependencyTemplates} */
		this.dependencyTemplates = new DependencyTemplates(this.outputOptions.hashFunction); // 依赖模板,用于生成依赖模块的代码

		/** @type {Record<string, number>} */
		this.childrenCounters = {}; // 存储子编译实例的计数器,用于支持多目标编译

		/** @type {Set<number|string>} */
		this.usedChunkIds = null; // 存储已使用的块ID

		/** @type {Set<number>} */
		this.usedModuleIds = null; // 存储已使用的模块ID

		/** @type {boolean} */
		this.needAdditionalPass = false; // 是否需要额外的编译遍历

		/** @type {Set<Module & { restoreFromUnsafeCache: Function }>} */
		this._restoredUnsafeCacheModuleEntries = new Set(); // 存储恢复自不安全缓存的模块条目

		/** @type {Map<string, Module & { restoreFromUnsafeCache: Function }>} */
		this._restoredUnsafeCacheEntries = new Map(); // 存储恢复自不安全缓存的模块条目映射

		/** @type {WeakSet<Module>} */
		this.builtModules = new WeakSet(); // 存储已构建的模块,用于避免重复构建

		/** @type {WeakSet<Module>} */
		this.codeGeneratedModules = new WeakSet(); // 存储已生成代码的模块,用于标记已处理的模块

		/** @type {WeakSet<Module>} */
		this.buildTimeExecutedModules = new WeakSet(); // 存储在构建期间执行过的模块

		/** @type {Set<string>} */
		this.emittedAssets = new Set(); // 存储已发出的资产,用于追踪已输出的资源文件

		/** @type {Set<string>} */
		this.comparedForEmitAssets = new Set(); // 存储已比较的资产,用于避免重复发出

		/** @type {LazySet<string>} */
		this.fileDependencies = new LazySet(); // 存储文件依赖,懒加载集合

		/** @type {LazySet<string>} */
		this.contextDependencies = new LazySet(); // 存储上下文依赖,懒加载集合

		/** @type {LazySet<string>} */
		this.missingDependencies = new LazySet(); // 存储缺失的依赖,懒加载集合

		/** @type {LazySet<string>} */
		this.buildDependencies = new LazySet(); // 存储构建时的依赖,懒加载集合

		// TODO webpack 6 删除,旧版本兼容
		this.compilationDependencies = {
			add: util.deprecate(
				/**
				 * @param {string} item item
				 * @returns {LazySet<string>} file dependencies
				 */
				item => this.fileDependencies.add(item),
				"Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)",
				"DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES"
			)
		};

		// 使用缓存来存储模块、资产和代码生成的状态
		this._modulesCache = this.getCache("Compilation/modules");
		this._assetsCache = this.getCache("Compilation/assets");
		this._codeGenerationCache = this.getCache("Compilation/codeGeneration");

		const unsafeCache = options.module.unsafeCache;
		this._unsafeCache = Boolean(unsafeCache); // 是否启用不安全缓存
		this._unsafeCachePredicate = typeof unsafeCache === "function" ? unsafeCache : () => true; // 不安全缓存的判定函数

	}
相关推荐
前端小趴菜058 分钟前
JavaScript 读取电脑复制的内容
前端·javascript
OK_boom36 分钟前
React状态管理器的应用
前端·javascript·react.js
再学一点就睡1 小时前
一文搞懂跨域问题:原理、解决方案与实战避坑指南
前端·javascript
六个点1 小时前
面试中常见的手写题汇总
前端·javascript·面试
Json_2 小时前
Vue computed Option 计算选项
前端·vue.js·深度学习
西陵2 小时前
一文带你吃透前端网站嵌入设计
前端·javascript·架构
给钱,谢谢!2 小时前
记录vite引入sass预编译报错error during build: [vite:css] [sass] Undefined variable.问题
前端·css·sass·vite
拉不动的猪3 小时前
react常规面试题
前端·javascript·面试
NaZiMeKiY3 小时前
HTML5前端第六章节
前端·html·html5·1024程序员节
李小白663 小时前
Vue背景介绍+声明式渲染+数据响应式
前端·javascript·vue.js