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

相關文章
相關標籤/搜索