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 (11)
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
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.
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.
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 😂