将命令行参数传递给package.json中的npm脚本

Ton*_*alo 13 npm package.json npm-scripts

我在package.json中有以下脚本:

"scripts": {
    "vumper": "node node_modules/vumper/index.js",
    "format": "prettier --single-quote -width=80 --write package.json"
 },
Run Code Online (Sandbox Code Playgroud)

'vumper'包接受命令行参数(例如'dv').我希望能够做的是拥有一个连续运行这两个命令的命令.

基本上,我希望能够运行:

npm run vumber dv
Run Code Online (Sandbox Code Playgroud)

然后

npm run format
Run Code Online (Sandbox Code Playgroud)

但在一个命令中,类似于

npm run my-build dv
Run Code Online (Sandbox Code Playgroud)

这将运行上述两个命令,正确接受命令行参数'dv'并将其传递给第一个npm run vumper.这可能吗?

Rob*_*obC 19

简答:

基本上,你想要的是拥有这样的npm脚本,<arg-here>通过CLI提供;

...
"scripts": {
  "my-build": "npm run vumper <arg-here> && npm run format",
  ...
},
...
Run Code Online (Sandbox Code Playgroud)

但是,不幸的是,npm没有内置功能来实现这一目标.

特殊的npm选项--(请参阅下面的解决方案1的结尾以获取有关此选项的更多信息),只能用于将参数传递给脚本的END但不能传递给MIDDLE.因此,如果您的两个命令顺序相反,则--可以使用以下选项:

...
"scripts": {
  "my-build": "npm run format && npm run vumper --",
  ...
},
...
Run Code Online (Sandbox Code Playgroud)

要克服没有内置功能将参数传递到脚本的MIDDLE的限制,请考虑以下解决方案:

  1. 有关仅限Bash的解决方案,请参阅"解决方案1"部分.

  2. 如果需要跨平台支持,请遵循"解决方案2"部分中描述的解决方案.


解决方案1 ​​ - Bash(MacOS/Linux/etc ..):

my-buildpackage.jsonscripts部分配置脚本以调用Bash shell函数,如下所示:

的package.json

...
"scripts": {
  "my-build": "func() { npm run vumper \"$1\" && npm run format; }; func",
  "vumper": "node node_modules/vumper/index.js",
  "format": "prettier --single-quote -width=80 --write package.json"
},
...
Run Code Online (Sandbox Code Playgroud)

说明:

命名的Bash函数func执行以下操作:

  1. 首先运行npm run vumper <arg>.由此,<arg>将通过CLI传递的shell参数.它在脚本中引用$1(即第一个位置参数 /参数).
  2. 随后它运行format通过命令命名的脚本npm run format.

这两个npm run命令使用&&运算符链接,因此第二个npm run format命令仅在初始npm run vumper <arg>命令成功完成时运行(即返回0退出代码).

运行my-build脚本:

my-build通过CLI 调用,您需要运行:

npm run my-build -- dv
Run Code Online (Sandbox Code Playgroud)

注意:

  1. 在这种情况下,尾随dv部分是将传递给您的vumper脚本的参数.

  2. --必须在参数之前指定特殊选项.该文档描述的--选项为:

    ...特殊的选项--是使用getopt分隔的选项的结束.npm会将所有参数--直接传递给您的脚本:...参数只会传递给之后指定的脚本,npm run而不会传递给任何前置或后置脚本.


解决方案2 - 跨平台:

对于跨平台解决方案(使用Bash,Windows命令提示符/ cmd.exe和PowerShell等成功运行的解决方案),您需要使用nodejs帮助程序脚本,如下所示.

run.js

让我们命名脚本的NodeJS run.js并将其保存在项目根目录下,在同一级别的package.json.

const execSync = require('child_process').execSync;

const arg = process.argv[2] || 'dv'; // Default value `dv` if no args provided via CLI.

execSync('npm run vumper ' + arg, {stdio:[0, 1, 2]});
execSync('npm run format', {stdio:[0, 1, 2]});
Run Code Online (Sandbox Code Playgroud)

的package.json

配置my-build脚本以调用run.js,如下所示:

...
"scripts": {
  "my-build": "node run",
  "vumper": "node node_modules/vumper/index.js",
  "format": "prettier --single-quote -width=80 --write package.json"
},
...
Run Code Online (Sandbox Code Playgroud)

运行my-build脚本:

根据解决方案1,要my-build通过CLI 调用,您需要运行:

npm run my-build -- dv
Run Code Online (Sandbox Code Playgroud)

说明:

  • run.js利用process.argv以获得通过CLI(例如传入的参数dv).如果在运行npm run my-build默认值时没有提供参数,则(即dv)将传递给vumpernpm-script.

  • run.js 还利用child_process.execSync(...)壳出 /调用两个npm run命令.

  • 我实施了解决方案1,效果很好 (2认同)
  • 是否有一个 cli npm 包可以简单地执行类似 `const args = process.argv.slice(3);` const command = args.reduce(` ``(res, arg, index) =&gt; res.替换(new RegExp(`\\$${ index + 1 }`, 'g'), arg),`` `process.argv[2]` `);` `const execSync = require('child_process'). execSync;` `execSync(命令, { stdio: [0, 1, 2] });` ?. 这样我就可以用 \" 包装任何脚本,并用这样的 cli 作为前缀,然后使用有序参数运行任何脚本... (2认同)

Mab*_*ten 14

Npm 现在 一个内置选项可以将 cli 参数直接传递给 scripts。cli 参数存储在带有前缀的环境变量中npm_config_<flagname>,它们需要非常严格的语法,形式为--<flagname>=<flagvalue>.

例子:

 "my-build": "npm run vumper %npm_config_myflag% && npm run format",
Run Code Online (Sandbox Code Playgroud)

在终端中,运行npm run my-build --myflag=my_value以执行npm run vumper my_value && npm run format

笔记:

要在 npm 脚本中引用环境变量,您必须使用特定于平台的语法,即%npm_config_myflag%在 Windows 或$npm_config_myflagLinux 中。

更新:

为了避免与用于配置 npm 本身的 npm_config 变量发生冲突的风险,只需在您的参数前面加上一个唯一的前缀,例如您的应用程序的名称。

潜在的冲突是一个非常普遍的问题,它适用于许多情况:任何应用程序都可以使用其他应用程序已经使用过的环境变量;因此,环境变量通常以应用程序的名称作为前缀(例如 NVM_HOME、JAVA_HOME)。但是这种潜在的冲突并不是避免使用环境变量的好理由。我认为同样适用于 npm params / npm_config env vars。该文档没有说明冲突的风险,这意味着我想它们应该像往常一样进行管理。

  • npm 也出于内部目的创建了自己的名为“npm_config_*”的环境变量。请务必为标志/选项选择一个名称(例如“--myflag=*”),该名称不会覆盖内部使用的名称,因为这可能会产生不需要的结果。您可以 cd 到项目目录并运行 npm run env 来列出 npm 添加的环境变量。例如,传递 `--tag=foo` 不是一个好主意,因为 npm 添加了 `npm_config_tag` 环境变量(它的值通常设置为 `latest`)。通过使用此方法,不确定 npm 将来可能会添加哪些内部“npm_config_*”变量,您最终可能会覆盖这些变量。 (3认同)
  • 特定于平台对我来说很关键。我在 Windows 上尝试 `$npm_config_myflag` 并失去了理智 (2认同)

dua*_*exf 7

我的首选方法是使用环境变量:

{
  "scripts": {
    "ncc-build": "ncc build $ACTION/src/index.ts -o $ACTION/dist",
    "build:pr-changelog": "ACTION=pr-changelog npm run ncc-build",
  }
}
Run Code Online (Sandbox Code Playgroud)

它应该可以在 UNIX 系统中工作。不过我不确定 Windows 平台的兼容性。

  • 是的,它不适用于Windows平台 (2认同)