How to publish npm packages?
Tags: react, javascript, npm, babel
Published: 2019-09-07 09:46:58

Publishing an npm package, it turns out, is not as difficult as one assumes it to be. This article will walk you through the process I followed when publishing a recent package of mine called `react-client-dimensions`. I chose to write the article with a very specific example rather than a general mock example since I find such articles more valuable, albeit the scope it covers is limited.

# What is the package?

Before I walk through the steps of publishing an npm package, let me first tell you about the package. In several of my hobby projects (mostly react), I need to render a different component based on the window (or client or viewport, whatever you want to call it) size. This makes it easier to handle specific requirements for a responsive layout where media queries are not as straightforward. So I wrote a custom hook that tells me what the client dimensions are, i.e. the width and height. I was using this hook across several projects, so I decided to publish it as an npm package. Now I can use it by just installing a dependancy rather than copy-pasting my code every time.

# Initial Setup: Got node? Okay, create directory.

Make sure you have node installed on your machine. A node installation will also give you npm out-of-the-box which is more than sufficient but I prefer to use yarn (which is what this article will use). Take your pick, they are substitutable with each other. You can install node from [here](https://nodejs.org/en/download/) and yarn from [here](https://yarnpkg.com/en/docs/install).

The first step is to create the project directory you want to publish. In my case, I create a folder called 'react-client-dimensions'.

```
mkdir react-client-dimensions
cd react-client-dimensions
```

# The all-important package.json

To generate your package.json file, run yarn init command inside your project directory. The CLI wizard will guide you through a series of steps to generate your package.json configuration. Alternatively, you can use yarn init -y which has a flag to quickly set you up with a default configuration.

![package.json](https://cdn-images-1.medium.com/max/1000/1*PwMz50068y-1iSigFLv7-g.png)

This is all that we need to publish the package. I prefer to publish the package at this point so that I can change the name if it's not available. I had initially tried the name react-window-size but it was already taken, so I settled for `react-client-dimensions`. To publish, you need an npm account. In your command line, authorize your login credentials using the command:

```
npm login
```
Before publishing, it is a good idea to add a license, changelog, and a readme file. NPM will always automatically include your `package.json`, readme, changelog and license no matter what.

```
touch README.md CHANGELOG.md LICENSE

```

I usually use the MIT license which can be found [here](https://opensource.org/licenses/MIT). My changelog file is typically in the following pattern.

![CHANGELOG.md](https://cdn-images-1.medium.com/max/1000/1*L4AYZn2Z8ytLGJHu9rdSCQ.png)

To publish our package to the registry run,

```
npm publish
```

# Writing the source code

Now we write the actual package. The meat and potatoes of what we want to achieve with the package. Typically source code is written in a directory called `src` which separates it from the rest of our codebase. This also makes it easier to bundle all your code into a lib or dist folder after you've pre-processed your code for production use using tools such as Babel or Webpack.

![Source Code](https://cdn-images-1.medium.com/max/1000/1*lN32-bVpRv9ofKN0sGHnlA.png)

There we have it. Our source code for the package. We're almost ready to publish it but not quite yet.

# Transpiling our code with Babel

The code we have written uses ES6+ syntax which is not supported in older browser versions. For example, arrow functions is an ES6 feature and you can see the status of support here. In order to make our code work across all environments, we use a compiler (called Babel) to compile our code and package it.

We install the dependencies (as dev dependencies) for Babel using the following command. These are dev dependencies because our packaged code does not depend on.

```
yarn add -D @babel/cli @babel/core @babel/preset-env
```

Babel is a JavaScript compiler that converts ES6+ code into a backward-compatible version of JavaScript in old browsers or environments. The Babel CLI (@babel/cli) is a command-line tool that provides your command line with the ability to run the babel-core API (@babel/core) on your source code.

With just these tools you will find that there is a lot more work that you need to do in order to micromanage the syntax transforms that are needed by your target environment. To simplify this, we add a preset (@babel/preset-env) which does this work for you in a concise manner.

Now we need to tell our babel configuration to use the preset-env that we installed. We can do this by adding our babel config to our package.json file. We edit our `package.json` file to look something like this.

![Updated package.json](https://cdn-images-1.medium.com/max/1000/1*QFT4c4lWubFi83yeldJObw.png)

The important changes you need to note here are:

1. Update main entry point to "lib/index.js" because that is where we ask babel to store our production-ready source code.

2. We added our @babel/preset-env preset to our babel config.

3. We added a "build" script which uses Babel CLI to transpile our code and put it inside the lib folder. You can run it using the command: yarn build.

4. Every time we publish we need to run the build command first. We can automate this step by adding a "prepare" script which npm automatically runs when you run: `npm publish`

5. We want npm to only publish our lib folder. So we include it in the files attribute.

In this case, we tell npm to publish our package only with certain files and folders (whitelist). Alternatively, you can choose to tell npm to avoid certain files and folders (blacklist) using the `.npmignore file`. However, I find blacklisting a more troublesome option than whitelisting. You can read more about these options [here](https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package) and [here](https://medium.com/@jdxcode/for-the-love-of-god-dont-use-npmignore-f93c08909d8d).

# Semantic Versioning

The source code we added is a new version for our package. NPM won't let you publish this version without updating the version attribute of your 1package.json` file. To do this, we follow a versioning system called Semantic Versioning. You can read more about this [here](https://medium.com/@jameshamann/a-brief-guide-to-semantic-versioning-c6055d87c90e).

We want to patch update our version. So we run `npm version patch` to update our version.

```
npm version patch -m "Added source code for useClientDimensions() hook"
```

Once our versioning is done, we are ready to publish our package. Simply run `npm publish` and you are done. Your package is out there now. :)

Check out my package `react-client-dimensions` here. Tell people about it if you find it useful.

Thanks for reading. Drop me a comment if you have feedback/suggestions. I highly appreciate those.

Have a good day.