The simple guide to write and publish your own Node.js NPM package

Have you written or want to write something great that you wish to share with others in the JavaScript community? Creating and publishing an NPM package is can be done with a simple process. This guide will show you how to create an NPM package project, prepare for release, and publish.

Prerequisite

Node.js installed

Create project

Move to a directory where to want to create your project and initialize a project configuration.

$ mkdir npm-tutorial
$ cd npm-tutorial
$ npm init

You'll be prompted with a few questions to get started with your project. The first would be the name which is what your package will be called on the NPM website. Aside from that, you can leave them to the default values for now and change them later in the created package.json file.

Now you should have a package.json file. Create two directories called src and dist.

29783c1b8ad9

The src/ directory will be your actual work space where the source ES6 code will be and the dist/ directory will be the transpiled ES5 code that will be distributed in NPM. The code is transpiled to ensure backward JavaScript compatibility, where we will use Babel. We are set it so that only the src/ directory gets committed into our Git source control, and only the dist/ directory gets published to NPM.

For that, create a .gitignore file and a .npmignore file. For .gitignore, add the following to ensure that the dist directory is ignored in commits.

# Distribution files
dist/

You can also add other common directories or files in your gitignore such as nodemodules/ if your package has dependencies. Refer here.

For .npmignore, ignore the src/ directory and also the test/ directory which we will create later. Add the following.

src
test

Setup

Index

First, we create an entry index.js file for the package. In the src/ directory, create the index.js file. We'll have to point to index.js as the entry file in the package.json.

{
  "name": "npm-tutorial",
  "version": "1.0.0",
  "description": "Your package description",
  "main": "./dist/index.js", // Here
  ...

Notice that it sets to index.js in the dist/ directory? It's because we want to point it to the transpiled version that we distribute to NPM. The index.js in the dist/ directory does not exist yet as we have yet to transpile the code from src/. To do that, we first have to set up Babel.

Babel

Install Babel and save it to your package.json as a development dependency. Use the following.

$ npm i --save-dev babel-cli babel-preset-es2015

Or if you prefer you can install babel globally as well, in which case you do not need to install it locally as above.

$ npm i -g babel-cli babel-preset-es2015

Before we transpile, add the following sample code to ./src/index.js so that we have some code to transpile.

function addTwoNum(num1, num2) {
    const total = num1 + num2;
    return total;
}

Run Babel to transpile your code.

$ ./node_modules/.bin/babel src --presets babel-preset-es2015 --out-dir dist

If you installed Babel globally, replace ./node_modules/.bin/babel with babel. Once done, you can view the index.js file generated in your dist/ directory.

"use strict";

function addTwoNum(num1, num2) {
    var total = num1 + num2;
    return total;
}

You can see that const is replace with var to support older JavaScript versions and the use of "use strict" for strict mode. Note that the strict mode enforces secure practices and can sometimes stop your transpiled code from working.

The command to run Babel is too long to remember so we add it to the package.json as a script.

"scripts": {
    "build": "./node_modules/.bin/babel src --presets babel-preset-es2015 --out-dir dist",
    "prepublish": "npm run build"
},

Now we can simply type npm run build to transpile our code. Add the build command to prepublish to ensure the build is run before publishing.

Export

Now we already have a simple library with a single function. We'll add more features into our library and export the functions. Add the following in your src/index.js.

function addTwoNum(num1, num2) {
    ...
}

function addThreeNum(num1, num2, num3) {
    const total = num1 + num2 + num3;
    return total;
}

module.exports = {
    addTwoNum,
    addThreeNum,
}

The export allows the function to be accessed. Now we are done and we have a simple library. Next we move on to writing test to checking if it works and simulate using the library.

Testing

Setup

Automated testing is essential for published packages. You want to make sure there's at least some level of testing to make production ready libraries. It may seem daunting at first if you are not familiar with automated testing but they are actually quite simple and extremely useful.

We'll use Mocha and Chai for testing. Mocha is a test framework and Chai is an assertion library used on top of Mocha with features that makes assertion (test condition) much more pleasant. Same with the previous package, either install them locally or globally.

$ npm i --save-dev mocha chai

or

$ npm i -g mocha chai

Write test

Mocha requires tests to be in a directory called test. Therefore, create a test/ director in the project directory. Any file placed inside the test directory is a test file and can be named anything you want depending on what you are testing. For this, we'll just create one file and name it test.js.

var chai = require('chai');  
var expect = chai.expect;

const simpleMath = require('../dist/');

describe('Simple Math', () => {
  describe('#addTwoNum()', () => {
    it('should return correct answer for 3 + 5', () => {
      const total = simpleMath.addTwoNum(3, 5);
      expect(total).to.be.equal(8);
    });
    
    it('should return correct answer for 13 + 9', () => {
      const total = simpleMath.addTwoNum(13, 9);
      expect(total).to.be.equal(22);
    });
  });
  
  describe('#addThreeNum()', () => {
    it('should return correct answer for 5 + 7 + 13', () => {
      const total = simpleMath.addThreeNum(5, 7, 13);
      expect(total).to.be.equal(25);
    });
    
    it('should return correct answer for 10 + 44 + 13', () => {
      const total = simpleMath.addThreeNum(10, 44, 13);
      expect(total).to.be.equal(67);
    });
  });
});

The test import/require (s) the library from the dist/ directory. Index.js is loaded by default when the file is not specified as above. This is a good method of simulating your library being loaded as if it was an installed package. Then we write tests to call different function and test them to work correctly.

Before we run the test, we have to ensure that the code is already build as the test is run on the dist/ code. You can run 'npm run build' again in case. Then to run mocha either:

$ ./node_modules/.bin/mocha

or for global install

$ mocha

To simplify the build and test, add/edit in your scripts in the package.json file.

"scripts": {
  "test": "npm run build && ./node_modules/.bin/mocha",
  ...
},

Now to build and test, we can simply run:

npm test

Check that the tests past, and you ready to publish.

Publish

This will show you the steps to publish to NPM. Do not actually this package!. Publish your package when you have one.

Package

You would want to ensure that your package.json is complete as NPM acquires info for the package listing from it. Ensure that your package info such as its name meets the NPM policy guidelines.

{
  "name": "my-package-name",
  "version": "1.0.0",
  "description": "Library to add numbers together",
  "main": "./dist/index.js",
  "scripts": {
    ...
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/github_username/repository-name.git"
  },
  "keywords": [
    "math",
    "addition",
    "numbers",
    "awesome"
  ],
  "author": "John Doe <john_doe_npm@outlook.com>",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/github_username/repository-name/issues"
  },
  "homepage": "https://github.com/github_username/repository-name#readme",
  "devDependencies": {
    "...
  }
}

Readme

It is recommended that you include a README documentation in your project. Create the README.md in your project directory and write documentation and project info as required.

NPM

First, you have to create and account and login into NPM. You can either create your account on the NPM website or in the console using npm adduser. Next, login with your console using npm login. You can type npm whoami to check that you are logged in.

Lastly, run npm publish. Go to https://npmjs.com/package/<your-package-name> to check that your package is up. Now you can brag to people about how easy it is to install your package.

Wei-Ming Thor

I write guides on Software Engineering, Data Science, and Machine Learning.

Background

Full-stack engineer who builds web and mobile apps. Now, exploring Machine Learning and Data Engineering.

Writing unmaintainable code since 2010.

Skill/languages

Best: JavaScript, Python
Others: Android, iOS, C, React Native, Ruby, PHP

Work

Engineering Manager

Location

Kuala Lumpur, Malaysia

Open Source
Support

Turn coffee into coding guides. Buy me coffee