Script the Pain Away

Script the Pain Away

Npm as your build tool

“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.

[xkcd](https://cdn.hashnode.com/res/hashnode/image/upload/v1618075418639/0Nehzmlap.html)xkcd

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.

Versioning

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"

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

Building

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

"libBuild": "ng build lib-shared"

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! 🐦

Packing

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"

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.

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! 👀

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!

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.

Did you find this article valuable?

Support Michael Karén by becoming a sponsor. Any amount is appreciated!