webpack 原理之编译前流程全解析

一、Webpack 初始化:命令入口的选择

当在终端输入 webpack 命令,流程从 Webpack 初始化环节开启,核心文件为 webpack/bin/webpack.js 。此阶段首要任务是判断 webpack-cli 的安装情况:

  • 检测与分支逻辑 :代码会先检查系统是否安装 webpack-cli 。若未安装,会进入安装命令判断流程,识别是 yarnpnpm 还是 npm 包管理器,接着询问用户是否安装(y/n 交互 )。若用户输入 n ,流程直接终止;输入 y ,则加载可执行路径 webpack-cli/bin/cli.js 继续执行 。
  • 本地与全局的选择 :若已安装 webpack-cli ,会进一步判断是使用项目本地的 webpack-cli 还是全局版本。优先检测本地是否有可用实例,存在则走本地逻辑,确保项目依赖环境的一致性;若本地无,才使用全局逻辑,避免因版本差异引发问题。

二、webpack-cli 流程:命令解析与实例化

进入 webpack-cli/lib/webpack-cli.js 后,runCLI 函数登场,它会新建 WebpackCLI 实例并执行 run 方法:

  1. 参数解析run 方法首要工作是解析命令行参数,借助 Commander.js 库,识别 --mode--config 等选项,明确用户执行命令的意图 。
js 复制代码
const { program } = require("commander");​
// 注册命令执行逻辑​
program.action(async (options, cmd) => {​
// 处理参数并启动后续流程​
await loadCommand(cmd, options);​
});​

// 解析命令行参数​
program.parse(process.argv);
  1. 回调与子命令 :通过 this.program.action() 定义回调,触发 parseAsync 解析参数。之后创建子命令,先调用 loadCommandByName 按名称查找对应命令,再用 makeCommand 创建子命令并添加回调。
  2. 触发与执行 :完成子命令配置后,再次触发 parseAsync ,随后运行 runWebpack 方法,为编译器创建做准备。
js 复制代码
//加载webpack 定位webpack/package.json的main指向的文件(webpack/lib/index->webpack/lib/webpack.js)
 async loadWebpack(handleError = true) {
        return this.tryRequireThenImport(WEBPACK_PACKAGE, handleError);
    }
 
async run(args, parseOptions) {
    this.webpack = await this.loadWebpack();
    async createCompiler(options, callback) {
            let compiler;
            try {
                compiler = this.webpack(config.options, callback
                    ? (error, stats) => {}
                        callback(error, stats);
                    }
                    : callback);
            }
            catch (error) {}
            return compiler;
        }
}
async runWebpack(options, isWatchCommand) {
        let compiler;
        compiler = await this.createCompiler(options, callback);
        if (!compiler) {
            return;
        }
    }

三、编译器创建

webpack-cli 流程末尾,会调用 createCompiler 方法,衔接至 webpack/lib/webpack.js

  • 实例化编译器createCompiler 内部通过 new Compiler() 创建编译器实例,同时整合配置信息,包括从命令行参数、配置文件(如 webpack.config.js )中获取的内容,初始化编译器的基础环境 。
  • 为编译准备 :编译器创建完成后,并非立刻开始编译,而是做好各项准备,比如加载插件(默认插件和用户自定义插件 )、初始化编译所需的钩子等,等待 compiler.run 方法调用,正式开启编译流程。
js 复制代码
const createCompiler = (rawOptions, compilerIndex) => {
    //创建编译器
	const compiler = new Compiler(
		/** @type {string} */ (options.context),
		options
	);
        
        //启用各种插件
	new NodeEnvironmentPlugin({
		infrastructureLogging: options.infrastructureLogging
	}).apply(compiler);
	if (Array.isArray(options.plugins)) {
		
			} else if (plugin) {
				plugin.apply(compiler);
			}
		}
	}
        //调用钩子
	compiler.hooks.environment.call();
	compiler.hooks.afterEnvironment.call();
	new WebpackOptionsApply().process(options, compiler);
	compiler.hooks.initialize.call();
	return compiler;
};

四、总结

从终端输入 webpack 命令,到编译器创建完毕,完整流程可概括为:

这一过程中,Webpack 巧妙处理了环境检测、命令解析、编译器初始化等环节,既保证了不同环境(本地 / 全局 )的兼容性,又为编译过程做好充足准备。

相关推荐
kyriewen10 小时前
Anthropic 估值逼近万亿美元,Claude Sonnet 5 + Claude Science 一天两连发
前端·ai编程·claude
小徐_233311 小时前
Wot UI 2.2.0 发布:Button 新增 subtle,VideoPreview 预览体验继续增强
前端·微信小程序·uni-app
天蓝色的鱼鱼13 小时前
关于 CSS 你可能不知道的属性,但关键时刻很有用
前端·css
泯泷14 小时前
第 2 篇:设计第一套字节码:Opcode、Instruction 与 Constant Pool
前端·javascript·安全
妙码生花14 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
泯泷14 小时前
第 1 篇:从 1 + 2 开始:亲手写出第一台 JSVM
前端·javascript·安全
团团崽_七分甜14 小时前
Spring Boot 核心知识点总结
前端
lichenyang45314 小时前
从一个按钮开始,理解 ASCF 框架到底在做什么
前端
古夕15 小时前
第三方 SSO 接入实践:redirect_uri 编码、回调一致性与跨项目联调
前端·vue.js