A task runner runs … tasks.
In the JS world, some module bundlers also act as a task runner, but it's more useful to think of the task runner as a separate thing.
Some task runners that I know of and would consider using:
Make
Make can be seen as a task runner that happens to come with file-based dependency management.
- Pro: Installed everywhere
- Con: You better hope your file names never contain spaces
Usage:
a-target-file: a-dependency
echo "some shell command that runs to create a-target-file"
a-dependency:
touch a-dependency
a-non-file-task:
echo "this always runs"
.PHONY: a-non-file-task
# ^ this declares it to actually be a non-file task
make a-non-file-task
npm scripts
- Pro: name tasks pre- and post- to run them before or after other tasks
- Pro: You can run project-local tools installed with
npm
directly without having to specifynpx
- Con: No dependency management
Con:
package.json
has no comments.You can fake it by:
- writing
//
lines anyways and hope that tools accept it - writing comments in a top-level
"//"
key - using duplicate keys and hope that tools are well-behaved and throw out the comment
- using extra dummy keys like
"scriptsComments"
- writing extra scripts that echo a comment out
But none of it beats actually having real comment syntax.
- writing
Usage:
Declare your tasks in package.json
:
{
"scripts": {
"dev": "python -m http.server 8080",
"preanother": "echo 'this is special and runs before `another`'",
"another": "npm run dev",
"postanother": "echo 'this is special and runs after `another`'",
"yet-another-task": "mkdir public"
}
}
npm run yet-another-task
This is also supported by Yarn (including Yarn 1):
yarn run yet-another-task
Just a bunch of scripts
A bunch of scripts will also work.
- Pro: flexibility
- Con: you'll most likely end up writing a bunch of boilerplate
Example:
- ./utils/publish.sh
- ./utils/build.sh
- ./utils/lint.sh