执行webpack命令,发生了什么?
想要了解当我们在终端中输入webpack的时候,到底做了什么?首先我们可以回顾下这篇文章
npm scripts 使用指南。
从文章中我们知道,我们可以直接在终端执行webpack命令,意味着我们在项目根目录下的node_modules/bin下能找到webpack.js。
这里以Mac为例,node_modules/bin的webpack.js是一个软链,源路径是在node_modules/webpack/bin/webpack.js。配置webpack命令的入口文件在node_modules/webpack目录下的package.json:
"bin": {
"webpack": "bin/webpack.js"
}
意味着终端输入webpack命令执行的文件是"bin/webpack.js"。这个文件的起始行是:#!/usr/bin/env node表示这个脚本是node的解释程序。
执行过程如下:
-
创建一个cli对象
const cli = { name: "webpack-cli", package: "webpack-cli", binName: "webpack-cli", installed: isInstalled("webpack-cli"), url: "https://github.com/webpack/webpack-cli" }; -
判断cli是否安装,从当前目录下的node_modules开始遍历查找webpack-cli目录,直到根目录。如果找到,返回true。否则返回false。
const isInstalled = packageName => { const path = require("path"); const fs = require("graceful-fs"); let dir = __dirname; do { if (fs.statSync(path.join(dir, "node_modules", packageName)).isDirectory()) return true } while (dir !== (dir = path.dirname(dir))); return false; }; -
如果已经安装webpack-cli,则执行
runCli(cli),这个函数就是找到webpack-cli/package.json中的bin配置,并执行该入口文件:"bin": { "webpack-cli": "bin/cli.js" },const runCli = cli => { const path = require("path"); const pkgPath = require.resolve(`${cli.package}/package.json`); const pkg = require(pkgPath); require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName])); }; -
否则命令行会提示,
Do you want to install 'webpack-cli' (yes/no):- 如果输入y,会调用
runCommand自动安装webpack-cli包,安装成功后,执行runCli(cli) - 否则会报错,让你自己安装并结束运行脚本。
- 如果输入y,会调用
-
安装webpack-cli包,runCommand函数中传入的是
npm install -D或者yarn add -D,通过启动一个子进程来执行命令。runCommand执行成功后会执行runCli。const runCommand = (command, args) => { const cp = require("child_process"); return new Promise((resolve, reject) => { const executedCommand = cp.spawn(command, args, { stdio: "inherit", shell: true }); resolve() }) })
本文是针对我所了解的执行webpack命令的基本流程,本文之后会继续更新runCli的具体执行过程以及webpack-cli又做了什么。
文章中如有不妥之处,欢迎指正。