webpack源码分析(2)---- webpack\bin\webpack.js

前言

上文讲到调用webpack指令实际运行的是node webpack\bin\webpack.js这段代码,咱们今天的目的就是分析webpack\bin\路径下的webpack.js文件node

源码

// 将 webpack.js 中的源码主体扣出来并添加注释

process.exitCode = 0;

// 定义命令执行函数
const runCommand = (command, args) => {
	// ...
}

// 定义判断包是否安装函数
const isInstalled = packageName  => {
	// ...
}

// 定义cli数组
const CLIs = [
	{
		name: "webpack-cli",
		package: "webpack-cli",
		binName: "webpack-cli",
		alias: "cli",
		installed: isInstalled("webpack-cli"),
		recommended: true,
		url: "https://github.com/webpack/webpack-cli",
		description: "The original webpack full-featured CLI."
	},
	{
		name: "webpack-command",
		package: "webpack-command",
		binName: "webpack-command",
		alias: "command",
		installed: isInstalled("webpack-command"),
		recommended: false,
		url: "https://github.com/webpack-contrib/webpack-command",
		description: "A lightweight, opinionated webpack CLI."
	}
];

// 执行cli数组中每一项的installed方法

const installedClis = CLIs.filter(cli => cli.installed);

// 根据返回值installedClis长度执行对应逻辑
if (installedClis.length === 0) {
	// ...
}else if (installedClis.length === 1) {
	// ...
}else {
	// ...
}

分析

代码简化以后更方便咱们理解他的做用,如今咱们来逐步分析这块代码的执行过程:webpack

第一步

const installedClis = CLIs.filter(cli => cli.installed);

第二步

isInstalled("webpack-cli")
isInstalled("webpack-command")

const isInstalled = packageName => {
	try {
		require.resolve(packageName);

		return true;
	} catch (err) {
		return false;
	}
};

// require.resolve函数会查询模块的带有完整路径的文件名,但并不会加载该模块。
// 因为咱们项目中只安装了webpack-cli,因此installedClis的值为[ true ]。

第三步

// 如下为简化代码

// 当installedClis的length为0时,则会提示用户必须安装一个webpack的cli模块并引导用户安装webpack-cli

if (installedClis.length === 0) {

	let notify =
		"One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:";

	for (const item of CLIs) {
		if (item.recommended) {
			notify += `\n - ${item.name} (${item.url})\n   ${item.description}`;
		}
	}

	console.error(notify);

	console.error(
		`We will use "${packageManager}" to install the CLI via "${packageManager} ${installOptions.join(
			" "
		)}".`
	);
	
	let question = `Do you want to install 'webpack-cli' (yes/no): `;
} else if (installedClis.length === 1) {
	// ...
} else {
	// ...
}

// 当installedClis的length为2时,会提示用户只能安装一个webpack的cli库,用户须要卸载其中之一。
if (installedClis.length === 0) {
	// ...
} else if (installedClis.length === 1) {
	// ...
} else {
	console.warn(
		`You have installed ${installedClis
			.map(item => item.name)
			.join(
				" and "
			)} together. To work with the "webpack" command you need only one CLI package, please remove one of them or use 		them directly via their binary.`
	);
}

// 当installedClis的length为1时

if (installedClis.length === 0) {
	// ...
} else if (installedClis.length === 1) {

	// 获取webpack-cli/package.json文件完整路径
	const pkgPath = require.resolve(`${installedClis[0].package}/package.json`);
	
	// 引入webpack-cli/package.json 包文件
	const pkg = require(pkgPath);
	
	// 引入webpack-cli/bin/cli.js 模块
	require(path.resolve(
		path.dirname(pkgPath),
		pkg.bin[installedClis[0].binName]
	));
} else {
	// ...
}

总结

经过上面的分析,webpack.js文件最终的目的就是引入 webpack-cli/bin/cli.js 模块。git

ok,下一篇cli.js见!github

相关文章
相关标签/搜索