Shell variables in NPM scripts

Small shortcut for using shell variable with default values in NPM scripts.

Sometimes I want to use a shell variable to form the script command. For example, if I want to serve static files, I could use the http-server command.

1
2
3
4
5
{
"scripts": {
"serve": "http-server"
}
}
1
2
3
4
$ npm run serve
Starting up http-server, serving ./
Available on:
http://127.0.0.1:8080

What if I want to pass a different port? I could pass it as additional command line argument

1
2
3
4
$ npm run serve -- -p 3000
Starting up http-server, serving ./
Available on:
http://127.0.0.1:3000

The port number is simple to pass. In other cases, we have things that are more complex. For example, we might want to serve different subfolders instead of serving the current folder. Imagine we have multiple builds, each under a Git SHA, and including the "latest" build

1
2
3
4
5
builds/
latest/
2a87534/
682b252/
...

By default we want to serve the "builds/latest". The NPM script can be

1
2
3
4
5
{
"scripts": {
"serve": "http-server builds/latest"
}
}

How can we pick a different folder then? We could create a different script command and have the user provide the folder.

1
2
3
4
5
6
{
"scripts": {
"serve:latest": "http-server builds/latest",
"serve": "http-server"
}
}
1
$ npm run serve -- builds/2a87534

The above solution seems weird, the user has to enter too much information. I would prefer to have the subfolder and default value logic inside the script command. Here is the solution I use.

1
2
3
4
5
{
"scripts": {
"serve": "SHA=${SHA:-latest}; http-server builds/$SHA"
}
}

The above solution works with both cases: serving the default folder and the specific build.

1
2
3
4
$ npm run serve
Starting up http-server, serving builds/latest
$ SHA=2a87534 npm run serve
Starting up http-server, serving builds/2a87534

That's it.