前言
上文讲到调用webpack指令实际运行的是node webpack\bin\webpack.js这段代码,我们今天的目的就是分析webpack\bin\路径下的webpack.js文件
源码
// 将 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 {
// ...
}
分析
代码简化之后更方便我们理解他的作用,现在我们来逐步分析这块代码的执行过程:
第一步
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 模块。
ok,下一篇cli.js见!