Script the Pain Away

Npm as your build tool

Michael Karén
Oct 21, 2018 · 5 min read
Image for post
Image for post
Picture from Hyperbole and a Half

“Insanity: Doing the same thing over and over again and expecting different results.”

Relating this article to the quote one could argue that if we have a script that can build different versions of our library, then that is insane.

So let’s get crazy!

I’m going to use the commands from my article ‘Get Started with your first Angular library’ and turn them into npm scripts.

I will also show how we can re-use these scripts for multiple libraries across platforms with the help of variables and cross-env.

And remember that we are doing this to free some time up. There are so many better things you could be doing while the scripts are running.

Image for post
Image for post
Image for post
Image for post

Why npm Scripts

  • No extra dependencies;
  • Directly consume a smorgasbord of npm packages;
  • Cross-platform;
  • No additional files.

The Goal

To be able to execute one script that should:

  1. Update version
  2. Build
  3. Pack

I’m assuming you have a basic knowledge of how to find and run the scripts, so I’m going to jump right into it.


We need to increase the version number before every build. We can do this with npm-version. Also, to update the correct package.json, we can use the prefix flag with the folder of our library.

npm-version works with major, minor and patch. We use patch in our script and maybe later when we feel ready to release our library we can venture with one of the other options.

Ok, let’s see some code! Add the script libVersion to patch our version and execute it with “npm run libVersion”.

"libVersion": "npm version patch --prefix projects/lib-shared"
Image for post
Image for post

The new version is 0.03, and our first script is working.


Next, we add our build script called libBuild and run it.

"libBuild": "ng build lib-shared"
Image for post
Image for post

Nice we have our second script working with a lot of beautiful colors.
This scripting thing is straightforward! 💪

Like this blog post? Share it on Twitter! 🐦


Now, let’s add our packing script and name it libPack. The prefix flag is not working here, so we have to change folders to our library folder before we run the pack command. We can use && for chaining our commands.

"libPack": "cd projects/lib-shared && npm pack"
Image for post
Image for post

We have a tarball!

One Script to rule them all

Now that we have more than one script to run we really ought to create the master script that we are calling lib and use it to run them all.

"lib": "npm run libVersion && npm run libBuild && npm run libPack"

Tip: run with -s to silence the logging.

Image for post
Image for post

Awesome! We got our new library packaged and ready with only one script.

Multiple Libraries

When we create our next library, we run into some problems since we have some hardcoded things in them. To remedy this, we need to use a variable that holds the name of our library. Let’s name it LIB and refactor our scripts.

"lib": "set LIB=lib-shared && npm run all -s",
"all": "npm run libVersion && npm run libBuild && npm run libPack",
"libVersion": "npm version patch --prefix projects/%LIB%",
"libBuild": "ng build %LIB%",
"libPack": "cd projects/%LIB% && npm pack"

And it still works. No?
Oh, I see the problem now… this guy is working in Windows! 👀

Image for post
Image for post

Cross Platform

The problem here is that not all command prompts are equal. There is a difference in how environment variables are set and utilized between different platforms. For example, most Windows command prompts do not understand when you set environment variables with NODE_ENV=production and as you saw we used set instead.

A solution for this is the popular package cross-env. With it, we can use the UNIX based POSIX standard and let cross-env take care of any cross-platform issues.

Cross-env module exposes two different bins, cross-env and cross-env-shell. If you want to do more than one thing you should use cross-env-shell and that is what I use in my examples.

First let’s install cross-env in our devDependecies.

npm i cross-env --save-dev

And now let’s refactor the scripts the cross-env way.

"lib": "cross-env-shell LIB=lib-shared npm run all -s",
"all": "npm run libVersion && npm run libBuild && npm run libPack",
"libVersion": "cross-env-shell npm version patch --prefix projects/$LIB",
"libBuild": "cross-env-shell ng build $LIB",
"libPack": "cd projects/$LIB && npm pack"

I have not yet been able to run libPack with cross-env, so if someone has a solution, please leave a comment below. For now run libPack without cross-env and use $LIB or %LIB% depending on what environment you are on.

The problem is that cross-env has an issue when we try to change directories. In the versioning, we can use prefix, but it does not seem to work with pack.

Oh, I can’t help myself. Let’s end with one more classic Windows error!

Image for post
Image for post

Let’s eat some cake now and let our scripts run in peace.

Update: I have written another article about npm scripting: ‘How to Command TFS with Npm Scripts’.

Call to Action

I always enjoy feedback so please 👏, 📝 and tweet 🐦.
Follow me on Twitter and Medium for blog updates.

Disclaimer: this article may or may not contain pop cultural references.


JavaScript news and opinion.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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