Up your npm game with these 4 practices

Yousif Al-Raheem
The Startup
Published in
5 min readJun 16, 2020

npm package “life hacks” for every JavaScript developer

A picture of npm package file

Prerequisites

If you don’t know what npm is then you should probably read about it before reading this article. This article is going to touch on recommendations and advanced concepts for those experienced with it. If you’re not, don’t worry, it’s not that complicated. I can recommend reading this article to get you started.

Let’s get started

There are a couple of ways to initiate your package.json in your new project. You would either use a template that you’ve tailored carefully throughout your work life that includes all the necessary information and scripts OR use npm init command to generate it. For the latter, regardless of whether you chose to fill up the information yourself or ask npm to answer “yes” to all the questions with--yes or -y flag. The command will only generate a few fields. From that point, you will start adding dependencies, scripts, and information as your project develops. It might reach a point where it gets messy and challenging to navigate.

Here are 4 practices you can use to enhance your package.json that improves both readability and maintainability:

First: Add all the necessary details

I put this as the first step because it’s really easy to obtain and necessary for any maintenance work you have in the future. Running the npm init command will generate the package.json file with these details:

You should fill up all the information with accurate information. If you are working with a team to develop this project then you can either omit the author or put the name of the team. You might be thinking, “Why is this important?” The answer is, once you complete the project and try to release it, you would probably consider versioning your releases with something like GitHub tags and releases, Azure DevOps artifacts, or using an on-premise artifactory. Depending on the solution, these pieces of information might come very handy when querying them during the process of setting up pipelines and builds.

Apart from the boilerplate details that come with running the npm init command, you should include at least the following details:

These details are most likely to be mentioned inside a published artifact for maintainers to follow the links when submitting issues or checking out the application using the “homepage” URL.

Second: Move commands to their scripts

There is a reason why we put commands into npm scripts. It’s just to make our life easier when it comes to running repetitive commands that might get hard to remember, especially when you come back to the project after some time working on something else. Imagine that you want to run a build command after you’ve developed a feature and tested it. Before building the solution you would want to clean up the dist (distribution) folder and run a linter. The command might look different based on the flags or tools you use but here is an example that uses rimraf and tslint:

It is recommended to move each one into a script that can be maintained individually and reused. Adding more flags to each one will increase its complexity making it even more challenging to maintain. This is not meant to decrease the amount of code your write, instead, it’s aimed to enhance readability and maintainability. Now try to clean up your scripts like this:

Third: Clean up your scripts with pre and post scripts

The example above solved an issue but created another. Now if I wanted to add test to the script with a cleanup command for unit tests as well as a deployment script with Github pages tool called gh-pages that runs after the build. It will look something like this:

Now, this is getting messy again. Thankfully, npm offers pre and post hooks to help you organize your scripts. Again, it will not have a smaller body of code, it will only enhance readability and maintainability. Using pre and post hooks in this example will look like this:

Pre and post hooks can be used with any custom command that you have. If you have a command called dostuff then you can set up predostuff and postdostuff.

Fourth: Use npm package variables

During our development time, we (my team) usually never write API function calls, instead, we rely on code generators like OpenAPI code generator with Swagger. If you add that script it’s not gonna look clean at all because it requires you to specify the URL to the swagger.json file. I know OpenAPI generator has an option of passing a config file, but I’m using this as an example of any other script that requires passing long variables like URLs. In that case, the script will look like this:

This command can be simplified by using npm package variables. Basically, you can access any piece of information inside the package by prefixing it with $npm_package_, for example accessing the name and version of the repository would be like this: $npm_package_name and $npm_package_version. You also need to remember that underscores replace dots. Imagine if you’ve imported the package.json file as an object in a JavaScript file and you’re trying to access the repository’s URL, you’ll have to do this:

const pkg = require('./package.json');
console.log(pkg.repository.url);

Now, replace pkg with $npm_package and dots with underscores to look like this $npm_package_repository_url. You might be thinking “What about arrays?”. Good question! Just pass the index number like this: $npm_package_keywords_0.

Now if we use npm variable to organize the aforementioned script, it should look like this:

Not only it’s easier to read with npm package variables, it’s easier to maintain. You can easily swipe URLs and other variables if it’s encapsulated in an object.

Caveat

For some reason, npm package variables will not work with a dollar sign ($) in Windows. In order to access npm variables, you have to wrap it with a percentage sign (%) like this:%npm_package_version%. The problem with this is that if you’re depending on a build pipeline that uses a Linux-based agent, the percentage sign won’t work. Sadly, there is no unified way of accessing npm variables in Windows and Linux-based OS (e.g. MacOS). I guess the only solution for you if you’re using Windows for development is to have two scripts like this:

This way, you can use the generate:win script in your Windows machine during development and use the generate script for your pipeline and other contributors who use Linux-based OS.

Last but not least

I should bring to your attention that if you are working with other developers in maintaining the project, they should also get familiar with these concepts, otherwise, it might get confusing for them. Especially with pre and post hooks, running npm run build that triggers a bunch of commands might get them confused. So might as well share this article with them just to get them in the same level of understanding.

--

--

Yousif Al-Raheem
The Startup

A Frontend Tech lead with masters degree in Software engineering. A tech enthusiast, a code geek, with a very sociable attitude.