Bootstrap

webpack webpack.js 源码解析

// 源码 121 ~ 193 行
const webpack = /** @type {WebpackFunctionSingle & WebpackFunctionMulti} */ (
	/**
	 * @param {WebpackOptions | (ReadonlyArray<WebpackOptions> & MultiCompilerOptions)} options options
	 * @param {Callback<Stats> & Callback<MultiStats>=} callback callback
	 * @returns {Compiler | MultiCompiler | null} Compiler or MultiCompiler
	 */
	(options, callback) => {
		const create = () => {
			if (!asArray(options).every(webpackOptionsSchemaCheck)) {
				getValidateSchema()(webpackOptionsSchema, options);
				util.deprecate(
					() => {},
					"webpack bug: Pre-compiled schema reports error while real schema is happy. This has performance drawbacks.",
					"DEP_WEBPACK_PRE_COMPILED_SCHEMA_INVALID"
				)();
			}
			/** @type {MultiCompiler|Compiler} */
			let compiler;
			/** @type {boolean | undefined} */
			let watch = false;
			/** @type {WatchOptions|WatchOptions[]} */
			let watchOptions;
			if (Array.isArray(options)) {
				/** @type {MultiCompiler} */
				compiler = createMultiCompiler(
					options,
					/** @type {MultiCompilerOptions} */ (options)
				);
				watch = options.some(options => options.watch);
				watchOptions = options.map(options => options.watchOptions || {});
			} else {
				const webpackOptions = /** @type {WebpackOptions} */ (options);
				/** @type {Compiler} */
				compiler = createCompiler(webpackOptions);
				watch = webpackOptions.watch;
				watchOptions = webpackOptions.watchOptions || {};
			}
			return { compiler, watch, watchOptions };
		};
		if (callback) {
			try {
				const { compiler, watch, watchOptions } = create();
				if (watch) {
					compiler.watch(watchOptions, callback);
				} else {
					compiler.run((err, stats) => {
						compiler.close(err2 => {
							callback(
								err || err2,
								/** @type {options extends WebpackOptions ? Stats : MultiStats} */
								(stats)
							);
						});
					});
				}
				return compiler;
			} catch (err) {
				process.nextTick(() => callback(/** @type {Error} */ (err)));
				return null;
			}
		} else {
			const { compiler, watch } = create();
			if (watch) {
				util.deprecate(
					() => {},
					"A 'callback' argument needs to be provided to the 'webpack(options, callback)' function when the 'watch' option is set. There is no way to handle the 'watch' option without a callback.",
					"DEP_WEBPACK_WATCH_WITHOUT_CALLBACK"
				)();
			}
			return compiler;
		}
	}
);

webpack 函数可以根据传入的配置选项创建 Webpack 编译器实例,并根据配置决定是否启动监听模式。

主要功能和逻辑

  1. 参数处理

    • 函数接受两个参数:options 和 callback
    • options 可以是单个 Webpack 配置对象或一个 Webpack 配置对象数组。
    • callback 是一个可选的回调函数,用于处理编译结果。
  2. 配置验证

    • 使用 webpackOptionsSchemaCheck 函数验证传入的配置是否符合预期。
    • 如果配置不符合预期,使用 getValidateSchema() 函数进行详细验证,并输出警告信息。
  3. 编译器创建

    • 根据 options 的类型(单个配置或多个配置),调用 createCompiler 或 createMultiCompiler 函数创建相应的编译器实例。
    • 处理 watch 选项,确定是否需要监听文件变化。
  4. 编译执行

    • 如果提供了 callback,根据 watch 选项决定是启动监听模式还是执行一次编译。
    • 在监听模式下,调用 compiler.watch 方法。
    • 在非监听模式下,调用 compiler.run 方法执行编译,并在编译完成后关闭编译器。
    • 如果编译过程中发生错误,通过 callback 返回错误信息。
  5. 无回调情况处理

    • 如果未提供 callback 且设置了 watch 选项,输出警告信息,提示需要提供回调函数以处理监听模式。
  6. 错误处理

    • 在编译过程中捕获任何异常,并通过 process.nextTick 调用 callback 返回错误信息

这段代码实现了 Webpack 的核心功能,包括配置验证、编译器创建、编译执行以及错误处理。

;