问题
问1:如何使以下命令更优雅?
// package.json
{
"scripts": {
"build:dev": "vue-tsc --noEmit && vite build --mode development",
"build:pro": "vue-tsc --noEmit && vite build --mode production",
}
}
答1:
// package.json
{
"scripts": {
"build": "vue-tsc --noEmit && vite build",
"build:dev": "npm run build -- --mode development",
"build:pro": "npm run build -- --mode production",
}
}
问2:如果命令变成下面这样怎么优化呢?
// package.json
{
"scripts": {
"build:dev": "vue-tsc --noEmit && vite build --mode development && echo build end",
"build:pro": "vue-tsc --noEmit && vite build --mode production && echo build end",
}
}
答2:这样传?
// package.json
{
"scripts": {
"build": "vue-tsc --noEmit && vite build && echo build end",
"build:dev": "npm run build -- --mode development",
"build:pro": "npm run build -- --mode production",
}
}
错,vite build 接收不到 --mode 参数
那我调换一下顺序不就行了?
"build": "vue-tsc --noEmit && echo build end && vite build"
真是大聪明,不过要求 echo build end
要在最后执行😏
这种情况有没有优雅的解决方案呢😅
分析
1. 先拜读 阮一峰 大佬的文章 npm scripts 使用指南
npm 脚本的原理非常简单。每当执行npm run,就会自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。
向 npm 脚本传入参数,要使用--标明。
2. 分析答1中 npm run build -- --mode development
是怎么执行的:
--
表示传参,a -- b
表示 b 作为字符串拼接在 a 后面,解析后的命令为 vue-tsc --noEmit && vite build "--mode" "development"
,所以执行 npm run build:dev
能成功
3. 答2为什么不可以:
根据前面的解释,答2执行 npm run build:dev
解析到的命令为 vue-tsc --noEmit && vite build && echo build end "--mode" "development"
显然这是不行的,vite build
没有正确接收到参数,会以默认 --mode production
执行
当然,调换一下顺序,将 && vite build
放在最后是可行的,"--mode" "development"
参数正好拼接在 vite build 命令后面,但是题目要求不能调换顺序,因为实际就有可能出现这种情况。
类似问题:npm run 执行package.json中的scripts配置时如何参数传递?
4. 简化问题
这个问题本质上就是 npm 命令如何以 --
之外的方式传参
// 伪代码
// 如果有这样一种传参方式
{
"scripts": {
"test": "echo ${参数}",
"test_": "npm run test 参数",
}
}
于是这个问题就简化为:执行 npm run test_ 时,能打印出 参数
传参方式
1. npm config 变量
1.1 第一个 Command Line Flags
就是前面讲到的 --
方式,我们看第二个 Environment Variables
直接上结果:
// 执行 `npm run test_` 会打印 `123`
{
"scripts": {
"test": "echo $npm_config_abc",
"test_": "npm run test --abc=123",
}
}
关键在于 --abc=123
会在 npm run 开启的 shell 里创建一个环境变量 npm_config_abc=123
1.2 注意: windows和mac/linux获取变量命令不一样
# windows
echo %npm_config_abc%
# mac/linux
# shell中,变量加{}和不加{}都可以
echo $npm_config_abc
# or
echo ${npm_config_abc}
为消除平台差异,可以使用 cross-var
或者 cross-env
插件
# install
npm i cross-var -D
# or
npm i cross-env -D
# scripts
cross-var echo $npm_config_abc
1.3 注意自定义变量 npm_config_abc 不要和 npm 内置变量冲突
比如 npm_config_m
、npm_config_v
等
1.4 注意和 package.json 中的 config 配置项 区分
// package.json
{
"config": {
"qwe": "456"
}
}
这个 config 变量是通过 npm_package_config_qwe
获取的
2. shell 变量
既然 npm run 执行的是 shell 命令,那么就可以通过创建 shell 变量来传参,
{
"scripts": {
"test": "cross-var echo $abc",
"test_": "abc=123 npm run test",
}
}
和 npm config 变量不同的是:
- 定义变量不需要加
--
,并且需要在使用变量之前定义 - 使用变量不需要加
npm_config_
3. 其他
3.1 在这个回答中,有提到用shell函数的方式
{
"scripts": {
"test": "test(){ echo $1 } test",
"test_": "npm run test -- 123",
}
}
实测是不可行的,执行 npm run test_ 会报错
sh: -c: line 1: syntax error: unexpected end of file
按理说思路是对的,可能写法有问题,希望有大佬指教一下🙇
3.2 利用 shell 脚本的 $n
传参方式是否可行
// 打印 123 456
{
"scripts": {
"test": "echo $2 $1",
"test_": "npm run test -- 123 456",
}
}
打印顺序不对,说明传参失败,而打印出来的 '123 456' 是因为 -- 123 456
被拼接在了 test 后面