x

Webpusher

Mark Lennox

a regrettable tendency to Javascript

Mark Lennox Javascript, C#, Python, machine learning, web, devops, mobile

(npm) publish, and be damned!

10th May, 2019

9 min read

I recently published my first npm package and my colleague, Attila Vágó, suggested I write up some notes on the process. I'll point out that I am not an expert on this (I don't even play one on TV!) so you should take this with a pinch of salt.

I'm going to outline why you might want to publish an npm package, then show you how easy it is, and finally, an overview of the configuration options you need to know.

Motivation - why would you ever publish an npm package?

fun!

happy, dancing, kid typing on old computer removing sunglasses to reveal another pair

It's fun to learn!

forking an existing package

Maybe an existing package doesn't do what you need. Maybe it has been abandoned. Maybe you need to add some new configuration and port it to es6 at the same time. Whatever the reason, you want it? you can rebuild it. You have the technology.

code sharing

You might want to share some code between your own projects. Publishing it as an npm package makes that easier. If you need to restrict access to your published library you can also publish your package to a private registry so that only you and your team can install it - not all the options cost money.

Publishing your package in three easy steps

Let's jump right in!

It is actually really easy to publish an npm package. I'll show you how to do that first and then show you how to properly configure your package so you publish only the files you want, and provide a good description of how to install and use your package.

1. Login to your npm account from the terminal

You'll need to have an account, so if you don't have one, visit https://www.npmjs.com/signup and create one.

On the terminal logging in is straightforward

$ npm login
# prompts you for your email and password

You only need to login once after starting / restarting your terminal.

2. Increment the version of your package

Unless this is the first time you've published, you'll have to increment the version of the package or npm will reject it as it expects an updated version every time you publish.

{
  "version": "1.0.0" // increment to 1.0.1
}

3. Publish!

The command below will publish your package

$ npm publish

# npm notice 
# npm notice 📦  [email protected]
# npm notice === Tarball Contents === 
# npm notice 1.5kB package.json       
# npm notice 1.1kB LICENSE            
# npm notice 2.0kB README.md          
# npm notice 1.5kB src/sort.js       
# npm notice 865B  src/fuzzy.js
# npm notice === Tarball Details === 
# npm notice name:          my-colourful-sorter                     
# npm notice version:       1.0.1                                   
# npm notice package size:  3.1 kB                                  
# npm notice unpacked size: 6.9 kB                                  
# npm notice shasum:        d2ffe8d1c9f8f284319efca30e610edee091d993
# npm notice integrity:     sha512-zbG1FeJIr3Ec1[...]EZaLTYm8TKaEg==
# npm notice total files:   5                                       
# npm notice 
# + [email protected]

Congratulations! I told you it would be easy.

Now for the slightly hard stuff - configuration.

Configuration - package.json

This is where the magic happens. The package.json file contains all the details npm needs to properly package and publish your library to npm, and then install to the developer's project when they choose to use it.

Apart from your dependencies, the top three properties of the package.json file you really need for publishing are:

  • files
  • name
  • version

There are further properties that are optional but usually required for anything more than a simple package:

  • description
  • keywords
  • main / browser

Finally, there are some less important fields that are also useful - I won't be covering them here:

  • engine
  • homepage
  • bugs
  • licence

Configuration - three is the magic number

files

This is optional, but I consider it the most important field in package.json, which is why I am putting it first in this list. As it suggests, this property determines what files will be included in your npm package. You will see a lot of suggestions to use .npmignore to blacklist whatever files you do not want included in the package - you probably shouldn't use it at all. Anyway, using the files field is recommended by npm.

The files field allows you to whitelist files by directly referencing them or using globbing patterns. These will override what is in your .gitignore and .npmignore file. As an example:

// package.json
{
  "files": [
    "src/**/*.js",
  ],
}

Will include all the js files in the root and sub-directories of the src directory. The ** pattern matches any subdirectory paths.

The patterns are not just a whitelist, you can exclude files too, making the files field very powerful. As an example, I like to have my unit tests in the same folder as my source files and these can be excluded using:

// package.json
{
  "files": [
    "src/**/*.js",
    "!src/**/*.test.js"
  ],
}

Regardless of what you have in the files field, these files are always included:

  • package.json
  • README
  • CHANGES / CHANGELOG / HISTORY
  • LICENSE / LICENCE
  • NOTICE
  • The file you specify in main field (see below)

name

This is the package name, and also what will be used to import your package into a module, so best to keep it short and memorable. It also needs to be unique, but you should search on https://npmjs.com to check your package name has not already been taken.

search to check the name my-super-duper-library has not been used

You can have a shorter package name if you scope your package name with your own npm username. If you want to call your npm package colors - a package that already exists - you can, if you use a scoped package name.

@paddingtonbear/colors

Installing this in a project would be just as simple.

$ npm install @paddingtonbear/colors

version

This is semver compliant. Keep it simple, start at 1.0.0. Every time you publish your package to npm you will need to increment the version - you can use the handy npm version command for this. If in doubt, increment the patch number each time you publish.

$ npm version patch

This will increment your version 1.0.0 package to version 1.0.1.

// package.json
{
  "version": "1.0.1"
}

There are npm libraries that help you publish to npm - the excellent np, for instance - but I won't be covering them here.

Optional configuration

description

Your package's elevator pitch. Keep it short and to the point, this is what appears in the search results on npmjs.com.

The description should tell you exactly what problem the package solves.

This is a bad example.

A super-duper npm package I enjoyed writing and hope you will enjoy using it to sort colourful and other types of lists

Ah, now this is just what I need for my wallpaper database project!

Configurable list sorter that allows sorting by colour

keywords

Any keywords you provide will be used to improve search results. Try and include useful keywords - node and nodejs won't help, for instance. In our hypothetical example these might be a good choice

{
  "keywords": [
    "color",
    "sort",
    "rainbow",
    "color-blind",
    "protanomaly",
    "deuteranomaly",
    "tritanomaly"
  ]
}

main / browser

When your npm package is imported into a module the main field defines what is returned.

For instance, if you define main as follows

// package.json
{
  "name": "my-colourful-sorter"
  "main": "src/sort.js"
}

Where the src/sort.js file in your npm package is

// src/sort.js
export default function doIt() { /* magic happens */ }

If you install your package in a project and import it into a module in that project, the import will be the doIt method from the src/sort.js file:

// wallpapers/index.js
import colourfulSorter from 'colourful-sorter';
    :
colourfulSorter(someList); // this will execute the `doIt` function in your src/sort.js file

The browser property is essentially the same as main but intended for libraries that will be used in the UI.

README

Your readme file is an essential part of your npm package. It's what helps a developer decide if your package is worth installing. At the very least it should describe what your package does, how to install it, and how to use it. Also, it's optional, but common to include badges highlighting the status of your CI pipeline.

description

You can't go wrong by including the name, and quoting the description from your package.json. Add a short paragraph expanding on the description and you're done.

Configurable list sorter that allows sorting by colour.

This sorter allows sorting colour names based on the hue 
of the colour they represent. It can be configured to sort 
in reverse order and can sort based on hues as affected 
by colour-blindness - protanomaly, deuteranomaly, or tritanomaly.

installation and requirements

Developers need to know if a certain version of nodejs is required, and whether the package is best used as a production or development dependency.

Requires Node 8 or higher. 

npm install --save @paddingtonbear/colors

How to use

You should give some working examples to highlight how to configure and use your npm package.

import colorsort from `@paddingtonbear/colors`;

const colorList = ['mango', 'chartreuse', 'vermillion', 'cyan', 'lavender'];

// ['vermillion', 'mango', 'chartreuse', 'cyan', 'lavender']
const result = colorsort(colorList, { order: colorsort.reverse });

API

The usage section should highlight some different ways of using your npm package, and even if you only have a small number of options you should still include an API section to explain them. An incomplete example is shown below.

colorsort(array, [options])
Returns an array of colours sorted in rainbow order.

options
Should be provided as an object literal. The properties and 
values are listed below

order
Can be `colorsort.normal` or `colorsort.reverse`

etc.

Author

You should probably provide your name, non-private email, twitter, linkedin, blog, etc.

Author
Michelin Mann <[email protected]>
- [@tirechap](https://twitter.com/tirechap)

Licence

Finally, you should list the licence you applied to your repo - the MIT licence is a good choice if you are not sure what to use.

How? Github allows you to add a licence to your repo when you create it. This will add a LICENCE file to your repo that includes the standard MIT licence text.

Github has more information about choosing and applying a licence

README template

I've provided a template README.md file that you can download and use in your own projects.