问题
I have the below scripts in my package.json:
\"scripts\": {
\"vumper\": \"node node_modules/vumper/index.js\",
\"format\": \"prettier --single-quote -width=80 --write package.json\"
},
The \'vumper\' package takes in a command line argument (such as \'dv\'). What I would like to be able to do is have a command that runs both of these in succession.
Essentially, I would like to be able to run:
npm run vumber dv
and then
npm run format
but in one command, something like
npm run my-build dv
which would run both of the above commands, correctly accepting the command line argument \'dv\' and passing it to the first npm run vumper. Is this possible?
回答1:
Short Answer:
Essentially, what you're wanting is to have an npm-script something like this, whereby <arg-here> is provide via the CLI;
...
"scripts": {
"my-build": "npm run vumper <arg-here> && npm run format",
...
},
...
However, unfortunately npm does not have a built-in feature to achieve this.
The special npm option --, (refer to the end of Solution 1 below for further info about this option), can only be used to pass an argument to the END of a script but NOT into the MIDDLE. So, if your two commands were in the opposite order, the -- option could be used like this:
...
"scripts": {
"my-build": "npm run format && npm run vumper --",
...
},
...
To overcome the limitation of there being no built-in feature to pass an argument into the MIDDLE of a script consider the following solutions:
For a Bash only solution refer to the "Solution 1" section.
If cross platform support is required then follow the solution described in the "Solution 2" section.
Solution 1 - Bash (MacOS/Linux/ etc..):
Configure your my-build script in the scripts section of package.json to invoke a Bash shell function, as shown below:
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"
},
...
Explanation:
The Bash function named func does the following:
- Firstly runs
npm run vumper <arg>. Whereby<arg>will be the shell argument passed via the CLI. It is referenced in the script using$1(i.e. the first positional parameter/argument). - Subsequently it runs the script named
formatvia the commandnpm run format.
These two npm run commands are chained using the && operator, so the second npm run format command will only run if the initial npm run vumper <arg> command completes successfully (i.e. returns a 0 exit code).
Running my-build script:
To invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Note:
In this instance the trailing
dvpart is the argument that will be passed to yourvumperscript.The special option
--must be specified before the argument. The docs describe the--option as:... The special option
--is used by getopt to delimit the end of the options. npm will pass all the arguments after the--directly to your script: ... The arguments will only be passed to the script specified afternpm runand not to any pre or post script.
Solution 2 - Cross-platform:
For a cross-platform solution, (one which works successfully with Bash, Windows Command Prompt / cmd.exe, and PowerShell etc..), you'll need to utilize a nodejs helper script as follows.
run.js
Let's name the nodejs script run.js and save it in the projects root directory, at the same level as 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]});
package.json
Configure your my-build script to invoke run.js as follows:
...
"scripts": {
"my-build": "node run",
"vumper": "node node_modules/vumper/index.js",
"format": "prettier --single-quote -width=80 --write package.json"
},
...
Running my-build script:
As per Solution 1, to invoke my-build via your CLI you'll need to run:
npm run my-build -- dv
Explanation:
run.js utilizes process.argv to obtain the argument passed via the CLI (e.g.
dv). If no argument is provided when runningnpm run my-buildthe default value, (i.e.dv), is passed to thevumpernpm-script.run.js also utilizes child_process.execSync(...) to shell-out/invoke the two
npm runcommands.
回答2:
I think you can use concurrently.
https://www.npmjs.com/package/concurrently
You have to install concurrently first then use it as follows,
Multiple commands can be run with arguments is supported
So in your case, it will be
concurrently "npm:vumber dv" "npm:format"
来源:https://stackoverflow.com/questions/51388921/pass-command-line-args-to-npm-scripts-in-package-json