node_modules
下 .bin
目录下有一个 webpack.cmd
脚本文件,组装定位了要执行的 webpack.js
文件
"%~dp0\node.exe" "%~dp0\..\webpack\bin\webpack.js" %*
将启动文件指向了 webpack
目录下的bin\webpack.js
。
在 webpack.js
文件中,有一个 runCommond
办法和 isInstalled
判断包是否装置函数,
const runCommand = (command, args) => {const cp = require("child_process");
return new Promise((resolve, reject) => {
const executedCommand = cp.spawn(command, args, {
stdio: "inherit",
shell: true
});
executedCommand.on("error", error => {reject(error);
});
executedCommand.on("exit", code => {if (code === 0) {resolve();
} else {reject();
}
});
});
};
const isInstalled = packageName => {
try {require.resolve(packageName);
return true;
} catch (err) {return false;}
};
installedClis
获取曾经装置的 cli,这外面重要的就是 CLIs 数组中第一行isInstalled("webpack-cli")
, 指向了webpack-cli
。
const installedClis = CLIs.filter(cli => cli.installed);
接下来依据 filter
办法找到曾经安装包,解决了包门路,通过最初的 require 导入了wbpack-cli/bin/cli.js
const path = require("path");
const pkgPath = require.resolve(`${installedClis[0].package}/package.json`);
// eslint-disable-next-line node/no-missing-require
const pkg = require(pkgPath);
// eslint-disable-next-line node/no-missing-require
require(path.resolve(path.dirname(pkgPath),
pkg.bin[installedClis[0].binName]
));
在 wbpack-cli/bin/cli.js
中,是一个 IIFE, 个别的 cli
文件中个别有二个操作,解决参数,将参数交给不同的逻辑(散发业务),文件中导入 webpack
,创立一个 webpack 实例。依据参数options
创立一个 compile
实例,挂载钩子,
const webpack = require("webpack");
let lastHash = null;
let compiler;
try {compiler = webpack(options);
} catch (err) {if (err.name === "WebpackOptionsValidationError") {if (argv.color) console.error(`\u001b[1m\u001b[31m${err.message}\u001b[39m\u001b[22m`);
else console.error(err.message);
// eslint-disable-next-line no-process-exit
process.exit(1);
}
throw err;
}
在文件结尾处,就找到了 webpack 打包入口 run
办法
compiler.run((err, stats) => {if (compiler.close) {
compiler.close(err2 => {compilerCallback(err || err2, stats);
});
} else {compilerCallback(err, stats);
}
});