在webpack 3中,webpack本身和它的CLI以前都是在同一个包中,但在第4版中,他们已经将两者分开来更好地管理它们。
ebpack 是一个静态的模块化打包工具,为现代的JavaScript应用程序服务
打包 bundler:webpack可以帮助我们进行打包,所以它是一个打包工具
静态的static:将代码打包成最终的静态资源(部署到静态服务器)
模块化module:webpack默认支持各种模块化开发,ES Module、CommonJS、AMD等
现代modern:前端开发的各种问题,催生了webpack的出现
webpack 安装
npm
install
webapck webpack-cli --save-dev
webpack 从 4.0 版本开始,在安装时,就必须要安装这两个东西。
webpack 是打包代码时依赖的核心内容,而 webpack-cli 是一个用来在命令行中运行 webpack 的工具。
但,webpack-cli对于打包文件不是必要的,这是为什么呢?
以 npm run build
命令来解析 webpack-cli 在代码打包中的作用,wk.config.js 为自定义webpack 配置文件
"scripts"
: {
"build"
:
"webpack --config wk.config.js"
}
当在命令行中执行 npm run build 时,会执行node_modules/.bin下的webpack可执行文件
这里有三个可执行文件,分别对应不同的平台
# unix 系统默认可执行文件,必须输入完整文件名
webpack
# windows cmd 中默认的可执行文件
webpack.cmd
# windows PowerShell 中可执行文件,可以跨平台
webpack.ps1
以webpack可执行文件内容为例:
#!/bin/sh
basedir=$(
dirname
"$(echo "
$0
" | sed -e 's,\,/,g')"
)
case
`
uname
`
in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w
"$basedir"
`;;
esac
if
[ -x
"$basedir/node"
];
then
"$basedir/node"
"$basedir/../webpack/bin/webpack.js"
"$@"
ret=$?
else
node
"$basedir/../webpack/bin/webpack.js"
"$@"
ret=$?
fi
exit
$ret
从代码中可以看到,会执行node_modules/webpack/bin/ 目录下的webpack.js,该文件主要代码如下:
// 该函数用于执行命令,例如用于下载需要的包
const runCommand = (command ,args) => {}
// 判断该包是否安装
const isInstalled = packageName => {}
// 该函数用于执行webpack-cli包中bin目录下的cli.js文件
const runCli = cli => {
const path = require("path");
const pkgPath = require.resolve(`${cli.package}/package.json`);
// pkgPath: D:\webpack\node_modules\webpack-cli\package.json
const pkg = require(pkgPath);
// pkg: webpack-cli的package.json 中的配置
// path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]): D:\webpack\node_modules\webpack-cli\bin\cli.js
require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
}
if (!cli.installed) {
// 判断 webpack-cli 是否安装
// 如果没有安装,询问用于是否安装 webpack-cli
...
...
} else {
runCli(cli);
}
该文件最重要的函数就是 runCli
,该函数可以执行 webpack-cli 包中bin目录下的cli.js 文件,也就是说在此之前的步骤只是为了找到cli.js文件,在此之后,webpack-cli 才发挥作用。
同时,webpack.js 文件也做了一些辅助判断,首先查看你是否安装了webpack-cli,如果没有安装,就会询问你是否安装(或手动安装)该包,如果选择不安装,那么程序运行到这就停止了。
接着打开webpack-cli/bin/cli.js
#!/usr/bin/env node
"use strict"
;
const importLocal = require(
"import-local"
);
const runCLI = require(
"../lib/bootstrap"
);
if
(!process.env.WEBPACK_CLI_SKIP_IMPORT_LOCAL) {
// Prefer the local installation of `webpack-cli`
if
(importLocal(__filename)) {
return
;
}
}
process.title =
"webpack"
;
runCLI(process.argv);
该文件的主要函数为 runCLI
,而 runCLI
又来自 bootstrap.js 文件,打开 bootstrap.js 文件
const WebpackCLI = require(
"./webpack-cli"
);
const runCLI = async (args) => {
// Create a new instance of the CLI object
const cli =
new
WebpackCLI();
try
{
await cli.run(args);
}
catch
(error) {
cli.logger.error(error);
process.exit(2);
}
};
module.exports = runCLI;
注意,到了这里才真正用到了 webpack-cli 暴露出的接口,cli.run(args) 用来处理命令行参数,此时args参数为:
[
'E:\nodejs\node.exe'
,
'D:\webpack\node_modules\webpack\bin\webpack.js'
,
'--config'
,
'wk.config.js'
]
最终,从以上整个过程,我们可以知道 webpack-cli 是用来处理命令行参数,并通过参数构建 compiler 对象,然后才是对代码进行打包的过程。
这同时也解决了前文提出的问题,为什么webpack-cli对于文件打包不是必需的。 既然 webpack-cli
只是为了处理命令行参数,那我们同样可以构建自己的cli来处理参数,比如 lyx-cli。在第三方框架中,React 和 Vue(未使用Vite的版本)也没有使用 webpack-cli.