Originally published at coreycleary.me. This is a cross-post from my content blog. I publish new content every week or two, and you can sign up to my newsletter if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets and other freebies.
A common scenario: as part of your npm start
script, you need to have more than one command run (like webpack --config webpack.server.js
and webpack --config webpack.client.js
).
Up until now you might have only run one command per script - often npm start
just does something like node server.js
.
So is there actually a way to run more than one command?
Rather than needing to have multiple scripts run, in multiple terminal/shell tabs, and having to remember the order in which to run them, it can be much easier.
We'll look at two ways of running more than one command as part of a npm script: sequentially and concurrently.
(and these will work for yarn
as well)
Sequentially
If you have commands that need to run in order, then using a double ampersand - &&
- in between those commands will make it so that the preceding command must finish before the next can start.
For simple demo purposes, imagine you have an index.js
file that just logs starting
and you want to log complete!
after it's finished. In your package.json
file, it would look like this:
"scripts": {
"start": "node index.js && echo 'complete!'"
}
And the output would look like:
> node index.js && echo 'complete!'
starting!
complete!
Concurrently
Now, if you need to run multiple commands at the same time - it doesn't matter what order they run in - the simplest way to achieve that would be to use a single ampersand between your commands.
But that presents a number of issues, the biggest being that we don't get good process handling.
For example, imagine the second command/process to run dies. The background process will keep running which potentially raises some problems:
- the background process will keep occupying resources
- it will still write to `stdout` and clutter the shell prompt
- if you try to run the script again, another background process will be created -> they will interfere with each other or cause the script to fail entirely (i.e.- port conflict)
- you’d have to kill the background processes manually to fix this
- or, a background process could die and you might not notice bc the exit message got buried somewhere in the logs
There is a npm package which solves this though: concurrently.
concurrently
allows for better process handling. It will clean up the processes automatically if they die. And it will give you more organized console output.
Let's look at an example:
"start": "concurrently --names 'SERVER,CLIENT' --prefix-colors 'yellow,blue' --kill-others 'json-server data.json' 'react-scripts start'"
--kill-others
will kill the other processes running if one process dies. And --prefix-colors
will allow us to more easily view the console logs - json-server data.json
logs will show in yellow and react-scripts start
will show in blue. We've also named them so we can tell by name which process is which.
concurrently
comes with a lot more configuration options (you can run other npm scripts besides npm start
too) so be sure to check out the documentation.
Wrapping up
But most importantly we now can better handle our processes. And we now know how to run more than one command/process as part of npm start
(or any npm/yarn script for that matter, we're not just limited to start
). As JavaScript/Node apps get more complex and have more complex start-up processes, it's extremely helpful to be able to have better control over these processes and not have to open up a bunch of shells.
Now you just have to use one command!
And if you found this post helpful, here's that link again to subscribe to my newsletter!