All the benefits of npm scripts without the cost of a bloated package.json and limits of json
Even though npm scripts have a ton of advantages (learn more), it can grow into an
unmaintainable mess in your package.json
file. Part of the problem is we're configuring scripts in json
which has fundamental issues (like no comments).
Put all of your scripts in a file called package-scripts.js
and use p-s
in a single package.json
script:
package.json
{
"scripts": {
"start": "package-scripts"
}
}
package-scripts.js
module.exports = {
scripts: {
lint: 'eslint .',
test: {
default: 'ava',
watch: {
script: 'ava -w',
description: 'run in the amazingly intelligent AVA watch mode'
}
},
build: {
default: 'webpack',
prod: 'webpack -p',
}
}
}
Then you can run:
npm start lint
npm start test.watch
But the fun doesn't end there! You can use a prefix:
npm start b # will run the build script
And if you want to speed things up even more, you can install npm-quick-run
and then:
nr s build.prod
Cool stuff right? And there's more on the roadmap.
Also check out the examples. You'll find some good stuff in there (including how to deal with windows and other cross-platform issues).
Note: You don't have to use the start
script of course. If you're writing a node application, you're likely using
this for starting your server. You could easily create a p-s
script and do: npm run p-s b
.
This module is distributed via npm which is bundled with node and should
be installed as one of your project's devDependencies
:
npm install --save-dev p-s
The CLI is fairly simple. It allows for a few options. The p-s
binary is available in your node_modules/.bin
directory when you install it locally in a project so you can use it in your npm
scripts. We also expose a
package-scripts
alias binary so you can use that as well if you'd like the script to be more clear.
$ p-s --help
Usage: p-s [options]
Options:
-h, --help output usage information
-V, --version output the version number
-s, --silent Silent p-s output
-p, --parallel <script-name1,script-name2> Scripts to run in parallel (comma seprated)
-c, --config <filepath> Config file to use (defaults to nearest package-scripts.js)
Available scripts (camel or kebab case accepted)
lint - Lint all files with eslint. Configuration is in package.json - eslint .
test - Run tests with AVA. See package.json for config - ava
test.watch - Run in the amazingly intelligent AVA watch mode - ava -w
build - The normal webpack UMD build for development - webpack
build.prod - The production webpack build - webpack -p
Will print out the help you see above (the available scripts are colored 🌈 and come from the config specified/default config).
By default, p-s
will log out to the console before running the command. You can add -s
to your command to silence
this.
Run the given scripts in parallel. This enables handy workflows like this:
npm start -p lint,build,cover && npm start check-coverage && npm start report-coverage
Use a different config
npm start -c ./other/package-scripts.js lint
Normally, p-s
will look for a package-scripts.js
file and load that to get the scripts. Generally you'll want to
have this at the root of your project (next to the package.json
). But by specifying -c
or --config
, p-s
will
use that file instead.
You can pass additional arguments to the script(s) that are being spawned:
npm start lint --fix # --fix will be passed on to the lint script
If you don't use -p
(because you don't need parallelism) then you can simply provide the name of the script like so:
npm start cover
That's all for the CLI.
p-s
expects to your package-scripts.js
file to module.exports
an object with the following properties:
This can be an object or a function that returns an object. See the annotated example below for what this object can look like (and different ways to run them):
module.exports = {
scripts: {
// you can assign a script property to a string
simple: 'echo "this is easy"', // npm start simple
test: {
default: {
script: 'echo "test things!"', // npm start test
description: 'just pass it on to npm... Do not take this config very seriously :-)',
},
otherStuff: {
// this one can be executed two different ways:
// 1. npm start test.otherStuff
// 2. npm start test.other-stuff
script: 'echo "testing other things"',
description: 'this is a handy description',
},
},
// this one can be executed a few different ways:
// 1. npm start k
// 2. npm start kebab-case
// 3. npm start kebabCase
'kebab-case': 'echo "kebab-case"'
},
}
Remember, I find it considerably nicer to just use npm-quick-run
and then I can do:
nr s k # runs npm start kebab-case
This object is used to configure p-s
with the following options:
Setting this to true
will prevent p-s
from outputting anything for your script (normally you'll get simple output
indicating the command that's being executed).
This was inspired by a tweet by @sindresorhus.
- scripty has a solution for this problem as well. The reason I didn't go with that though is you still need a line for every script (one of the pains I'm trying to solve) and a each script requires its own file (one of the benefits of npm scripts I wanted to keep).
Thanks goes to these people (emoji key):
Kent C. Dodds 💻 📖 🚇 💡 |
David Wells 💻 |
Abhishek Shende 💻 |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT