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

相关推荐
css趣多多2 小时前
ctx 上下文对象控制新增 / 编辑表单显示隐藏的逻辑
前端
_codemonster2 小时前
Vue的三种使用方式对比
前端·javascript·vue.js
寻找奶酪的mouse2 小时前
30岁技术人对职业和生活的思考
前端·后端·年终总结
梦想很大很大2 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
We་ct2 小时前
LeetCode 56. 合并区间:区间重叠问题的核心解法与代码解析
前端·算法·leetcode·typescript
张3蜂2 小时前
深入理解 Python 的 frozenset:为什么要有“不可变集合”?
前端·python·spring
无小道2 小时前
Qt——事件简单介绍
开发语言·前端·qt
广州华水科技2 小时前
GNSS与单北斗变形监测技术的应用现状分析与未来发展方向
前端
code_YuJun3 小时前
corepack 作用
前端
千寻girling3 小时前
Koa.js 教程 | 一份不可多得的 Node.js 的 Web 框架 Koa.js 教程
前端·后端·面试