How I Built and Deployed my First Open-Source NPM Library
Tags: javascript, webdev, programming, tutorial
Published: 2022-02-21 15:55:40

## Overview

If you develop applications in Javascript, I’m sure you’ve used NPM to install many of the libraries which help you build them. Today, I’ll be giving you an overview of what it’s like to develop your own NPM library and how to use Github to manage releases, docs, and tags.

## Getting Started

First off, before developing your own open-source NPM library, you’ll need to determine if what you’re building will be helpful to other developers.

For example, when determining what I should build first, I found that there were little to almost no SDKs for the CircleCI V2 API and none in Javascript with Typescript declarations. This led me to build an SDK for the API in Typescript, with support for browsers and NodeJS.

## Best Practices

### Testing

To prevent as many bugs as you can, it’s important to have extensive test coverage in your library. If you’re making API calls like my library, mocking is extremely useful as it eliminates the third-party dependency and purely tests the functionality of your code. Here’s an example of a test I wrote that mocks an Axios GET API call:
{% gist https://gist.github.com/jithenshriyan/6cca4e86844210f09125887938a175da.js %}
Using [Jest](https://jestjs.io/docs/getting-started), I mock the Axios library. Then within the test group, before running each test, I instantiate a new client of my SDK. Within the test, I mock the return value for a get call and then call my SDK and expect the response to be the data I mocked.

### Documentation

Documentation is especially important for open-source libraries as users will need to know how to install and use them. I personally used [TypeDoc](https://typedoc.org/) for my project to automatically generate the documentation for the descriptions and types I’ve included in my code.

## Preparing for Release

Once you’ve got all the code written, have extensive test coverage, and include documentation for your library there are a couple of things in your codebase that we can add if you haven’t already, which will make it easier to use your library and deploy it.

### Code Bundling

Bundling essentially compiles all of your exported code and dependencies across multiple files into a single file without formatting or white spaces to reduce file size. You can have bundles for different environments such as the browser and/or NodeJS. It will also mean that users can import all of your code from the root without having to specify directories.

Without bundling

    import { Hello } from '@hello/package/src/components/hello'

With bundling

    import { Hello } from '@hello/package'

I personally use [Rollup](https://rollupjs.org/guide/en/) to bundle my code as it has a vast ecosystem of plugins and is very popular for NPM libraries. For a more detailed explanation on using Rollup, I recommend reading [An Introduction to the Rollup.js JavaScript Bundler](https://www.sitepoint.com/rollup-javascript-bundler-introduction/) by [Craig Buckler](undefined).

### Linting

Linting helps identify bugs and increase code consistency. I personally use [ESLint](https://eslint.org/) as it finds errors consistently, automatically fixes common issues, and supports custom rules and the use of configurations from companies such as Airbnb and Google.

## Releasing

Now we’re ready to release our library to NPM. I’ll be showing you how I used semantic versioning and automation to publish my library to NPM and docs to Github pages.

### Versioning

The majority of open-source libraries use Semantic versioning to keep versions consistent and easy to understand. Essentially, according to Semantic versioning:
>  MAJOR version when you make incompatible API changes (e.g. 1.0.0 to 2.0.0)
>  MINOR version when you add functionality in a backward-compatible manner (e.g. 1.0.0 to 1.1.0)
>  PATCH version when you make backward-compatible bug fixes (e.g. 1.0.0 to 1.0.1)

Source: [Semantic](https://semver.org/)

NPM has built-in commands which enable you to increment versions. Here is the command and options available:

    npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]

When run, package.json, package-lock.json, and if present, npm-shrinkwrap.json will be updated with the new version.

### Automation

I used Github Actions to automate the process of releasing my npm library and deploying docs onto Github pages. I’ll be breaking down the workflow I built to release my library to NPM.
{% gist https://gist.github.com/jithenshriyan/ac5a2bbba58b64735f5356b59ae4be65.js %}
### Events

Actions need an event to trigger the workflow. In lines 3–7 you can see how my workflow is triggered by a push to the master branch or a workflow dispatch (manual run from the UI). For a list of more events, see [here](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows).

#### Jobs

Jobs define the individual steps that run within a workflow and can be dependent on each other. For example, the deploy job (line 21) is dependent on the test job (line 10). We wouldn’t want to deploy if the tests are failing right? The jobs I’ve defined are as follows:

#### Test Job
The test job configures node and runs two commands to install dependencies and run the test script.

#### Deploy Job
The deploy job configures node, installs dependencies, configures the registry URL, and publishes my package to NPM with public access. I’ve also added a secret called NPM_TOKEN to environment variables to authenticate my request to publish. NEVER directly paste secrets into actions. [Here’s how to create an encrypted secret in Github.](https://docs.github.com/en/actions/security-guides/encrypted-secrets)

#### Docs job
The docs job configures node, installs dependencies, builds the docs folder using [TypeDoc](https://typedoc.org/), and using a third-party library deploys the generated folder onto the gh-pages branch. Here’s how to enable docs on your Github repo.

![](https://cdn-images-1.medium.com/max/5200/0*acFVs-KxczxKJ8PM.png)

Source: [Library Carpentry](https://librarycarpentry.org/lc-git/05-github-pages/index.html)

## Final Steps

Now that we’ve released our library to NPM, we can create a release and tag in Github.

### Github Releases

Releases in Github can be used to inform users of new versions and changes made to the library. Tags are created alongside releases that contain the source code for the repository at that specific point in time. [Here’s how to create releases and tags in Github.](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release)

That's it! I hope my journey to releasing my first NPM library helps you launch your own. Feel free to check out my open-source library and share any feedback you have on the library or the article!
[**GitHub - jithenshriyan/circleci-v2-sdk: Typescript SDK for CircleCI V2 API**](https://github.com/jithenshriyan/circleci-v2-sdk)