Access variables in npm scripts

Increase the flexibility of your npm scripts

Image for post
Image for post

A while ago, almost all build tasks were managed by tools like grunt or gulp.

Depending on the project, people needed to understand the configurations and structures of the build tool which introduced some unnecessary complexity.

Since almost everybody is using as their package manager, it makes sense to profit from its ability to run scripts. scripts are managed inside our and can be executed with the command.

Compared to grunt or gulp files, they are easier to understand and maintain.

Flexible npm scripts

What do we mean when we talk about flexible scripts? We talk about scripts that can access variables and pass them to another script. Let’s have a look at the following graphic, which illustrates this concept further.

Image for post
Image for post

We have an environment with a variable. In this example, a variable called which has the value . We want to pass in this variable to our script, access it, and pass it to the third-party library which we call in our script.

To illustrate how this concept can be implemented, we are going to use a simple use case that you are probably all familiar with. Serving a simple webpage over an HTTP server.

Serving HTML pages on different ports 🍸

Let’s imagine we have the following static HTML page which we want to serve.

<html>
<body>
<h1>Testpage</h1>
...
</body>
</html>

The first thing we need is a web server. So, let’s go ahead and grep one. I favor the package.

npm i -D http-server

To start our page, we also add a simple task to the scripts section in our .

"start": "http-server"

If we now open a terminal of our choice and type an HTTP server starts up and serves our on port 8080 which is the default port the package uses.

So what if for some reason we need to start up our application on another port than 8080?

Let’s first check the docs of our module. We can see that we can specify the port via flag. Ok, easy, we can go on and add another build script like the following one.

"start-port-3000": "http-server -p 3000"

But this is not very flexible, right! Imagine we would need to do that for other ports as well. Our would become cluttered.

So there must be a more elegant way!

Follow me on Twitter or medium to get notified about my newest blog posts!🐥

Accessing external arguments in NPM scripts

It would be nice to let the consumer of our script decide on which port the should be started. So instead of adding another script, we can adjust our start script to access a port variable which will be passed to our script.

"start": "http-server -p $PORT"

The variable is now controlled by the caller of the script. So he can set the desired and pass it to our script.

PORT=3000 npm run start

Awesome! The variable is set to . It is then accessed by our script and passed to the . So we already implemented the desired behavior. Done!

✋Wait, not so fast.

This approach is helpful and flexible. But it has one major downside. Our script will not work if somebody forgets to set the variable. Gasp 😧

Use a default value

Default values are a great way to handle undefined values. We use a predefined value instead. Inside our script we can achieve that by using the following syntax;

"server:start": "http-server -p ${PORT:-8080}"

With this approach, our script is flexible and robust. The user decides if he wants or doesn’t want to pass in a port from outside.

Accessing variables in multiple scripts 🗂️

While this approach works great for single scripts, it’s crucial that it also works with multiple scripts than run sequential or even in parallel.

So imagine we would like to add another script which logs a sweet message once the server starts.

"log": "echo \"Success: Server successfully started on port \" + $PORT"

To run the task above together with our startup task, we need to install a package called as a dev dependency.

npm i -D npm-run-all

Let’s group those tasks by using the same prefix so that they can be run in parallel by using the command .

"server": "npm-run-all -p server:*",
"server:start": "http-server -p ${PORT:-8080}",
"server:log": "echo \"Success: Server successfully started on port \" + ${PORT:-8080}",

We can then set the port and run them all together.

PORT=3000 npm run server

Which results in the following output:

> echo "Success: Server successfully started on port " + $PORTSuccess: Server successfully started on port  + 3000
Starting up http-server, serving ./
Available on:
http://127.0.0.1:3000
http://192.168.1.126:3000
Hit CTRL-C to stop the server

Variables are set on the current process as environment variables. Therefore they can either be accessed by a single script or even by multiple scripts.

Further use cases 🔭

The example above is a straightforward example to illustrate how to access variables inside your scripts. We went through this example because it's quite simple and explains the cause.

However, you may not really need it in practice because you normally do not change the port to often. But there are more complicated practical use cases where you are forced to use the approach described above.

Imagine you have a library which gets published to . The whole setup uses conventional commit messages to automatically bump the version of the package inside a build step of your pipeline.

In such a scenario, the new build version is only available in your build environment. If you, for example, want to do something with the new version like updating the version of your or simply display it on a component by overriding some string inside an script — you are forced to access the variable from the outside.

Conclusion

Accessing variables inside your scripts makes your scripts more flexible.

It is especially useful when you use it inside a pipeline or some other environment where you need to access variables in your NPM script.

🙏 If you find this post helpful then give some claps by clicking on the clap 👏🏻 button below.

Claps help other people finding it and encourage me to write more posts

Feel free to check out some of my other articles about Front End development.

Written by

Passionate freelance frontend engineer. ❤️ Always eager to learn, share and expand knowledge.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store