Custom Arguments
Lets imagine that you have a NPM script to lint your application. Something like that:
"scripts": { "lint": "eslint './src/**/*.{js,ts,tsx}'" }
Then you decide to add a lint --fix in quiet mode because sometimes you want the linter to fix the errors quietly for you. Then you add another script:
"scripts": { "lint": "eslint './src/**/*.{js,ts,tsx}'", "lint:fix": "eslint './src/**/*.{js,ts,tsx}' --quiet --fix" }
Your lint:fix
is basically your lint
script with two new params. So, you can rewrite it to pass the params directly to the lint
command instead, without repeat it:
"scripts": { "lint": "eslint './src/**/*.{js,ts,tsx}'", "lint:fix": "npm run lint -- --quiet --fix" }
This approach is more succinct and scalable. If you change your lint
command, all the variations will inherit the modifications. Is also easier to read and quickly understand.
The --
notation tells your script to pass the parameters to the current command invoked by NPM. From the NPM docs: "NPM will pass all the arguments after the --
directly to your script". This feature is available on NPM >=2.0.0 | See the Docs. You can pass parameters to any command.
Named Parameters
From NPM docs: "Any environment variables that start with npm_config_ will be interpreted as a configuration parameter | See the Docs. That said, you can use the npm_config_
variable to pass named parameters to your NPM scripts executions.
Lets imagine that you have a serve
script that can serve your application in 4 modes: development
, staging
, test
and production
based on your NODE_ENV. So, you could have the following NPM scripts:
"scripts": { "serve": "nodemon index.js", "serve:dev": "NODE_ENV=development npm run serve", "serve:staging": "NODE_ENV=staging npm run serve", "serve:test": "NODE_ENV=test npm run serve", "serve:prod": "NODE_ENV=production npm run serve" }
Cool, mission accomplished: you can serve your application based on your stage
, that is also very useful. But we can refactor this code to use only one script, and pass our stage as an argument using the npm_config_
variable like that:
"scripts": { "serve": "NODE_ENV=$npm_config_stage nodemon index.js" }
Now we can pass our stage
parameter ($npm_config_stage) to modify the NODE_ENV when calling our script like that:
npm run serve --stage=development
You can pass any value to the stage
parameter, like npm run serve stage=whatever
.
Also you could want another name, like myvar
. So, you would call npm run serve --myvar=whatever
and your npm_config_
var would be $npm_config_myvar
.
Conclusion
Using Custom Parameters and Named Variables allow your NPM scripts to be smaller, easy understandable and maintainable. Thats all folks :)
Cover Image by Luca Bravo @ Unsplash
Top comments (12)
Nicely explained but I contradict on the usage of last set of commands. The sole reason to write four different scripts is to reduce the pain of typing
npm run serve --stage=development
every time even in dev environment. Just my perception, you might have different views on it.thats a fair point. in this case, i would prefer to add a new "serve:dev" with the proper stage flag. but I think it did its job as an example (?) :P another way would be to infer the 'development' mode on your application when there is no flag.
This is great. Thanks for pointing to this npm feature.
I have a question, if i want to have argument that is purely a flag, how can i pass it to npm script. Example:
I tried this and it didnt work:
Is there a way to pass boolean type of flag to npm script?
NOTE:
I dont want to use
--
delimiter to pass arguments as it is required fornpm
.hi there. i have the same question. have you sovled this question? would you perfer to share me your solution?
Hey. No luck on my side. I did not look anywhere else on this topic. This was mostly my curiosity rather than real life need.
If i stumble upon anything i will post it here.
Hello,
this does not work on Windows env. How could I make it work ?
Im really sorry, but i have only Unix-Like Systems at hand now, so i cant help you since i have no way to test it on a windows system. But you can take a look on the NPM official documentation:
docs.npmjs.com/cli/v7/using-npm/co...
It doesn't tell anything about config variables specificity for windows, so maybe you can do a review on your scripts following the docs to do a double check.
Try to install cross-env as a dev dependency. Then you have a universal way to declare scripts with parameters / arguments. :)
npmjs.com/package/cross-env
Exactly what I was looking for. Thank you for the write up!
I've always thought that existed a way of doing things like that but never read the docs to see how to use these features. Thanks for the great article, I absolutely will use this for now on.
For people using PNPM, this doesn't work with it. You must use NPM to have the named param works. Not sure about yarn tho.
npm run serve --stage=development ? uh no no no
npm run serve:dev ? not even this...
i make a alias for them on linux
for example:
alias nrs:d='npm run serve:dev'
easy 😂