Publishing your open source package to npm

Node package manager (npm) is the package manager that ships with a fresh Node.js install and is arguably the de facto package manager you will use when creating and publishing your open source Typescript/Javascript project(s). Yarn is the most popular and widely known competitor to npm, but this guide will focus on publishing to npm. The following steps though can likely be slightly modified to publish them to Yarn as well (I'll leave it up to the reader to go through that exercise if they need to).

When I first created a package I thought would be cool to open source and allow use by others, I remember having to search in various places across the internet from the npm website to several disparate tutorials to find a complete list of information to publish your package. I feel this might be a barrier to entry for new folks that could be removed if there was a single, short, but complete list of steps to get started.

1. Finding an available name

This can likely also be the last step in this list, but because it's nice to go ahead and scaffold your project with the name you will call it, you can confirm up front whether the name you'd like to use in npm is available.

To do this, simply navigate to https://www.npmjs.com/package/$YOUR_PACKAGE_NAME and if you get a 404 error, your package name is available to use! For example, if you wanted to name your package mygreatpackage, the following screenshot shows this package name is available to use on npm today.

npm package is available!

2. Add this name to your package.json

What a package.json file is and does within the context of writing a Typescript or Javascript package is outside of the scope of this tutorial, but what is in scope is making sure npm knows what your package is named and where to publish it. You need to make sure the name field is set to the name you decided on in step 1. above.

There might be a lot more fields populated in your package.json, but here illustrates what the name should look like assuming you name your package mygreatpackage

{
  "name": "mygreatpackage",
  "version": "0.0.1",
  "description": "The best open source package available on the internets."
}

3. Consider hooks/callbacks that need to be ran at publish time of your package

We won't go into detail on the various scripts and callbacks that can be executed when you publish your package to npm (or other package managers) since there is an entire blog post or two we could write discussing it, but you should consider, understand, and possibly use the various lifecycle hooks available at publish time so your package is completely ready to be used when a random user on the internet installs it in their project.

4. main and/or bin

Is your project a library that will be used inside a user's code base like Vue or React? Is it a CLI tool that someone should be able to execute to accomplish some goal from the terminal like Gulp or Grunt? The answer to these questions determines whether main or bin (or both) need to be populated in your package.json. If you built a library that a user should be able to use in their project with import MyGreatPackage from 'mygreatpackage', you should provide the entry point to your library in the main field

{
  "name": "mygreatpackage",
  "version": "0.0.1",
  "description": "The best open source package available on the internets.",
  "main": "./dist/mygreatpackage.js"
}

and if you have an executable that should be able to be called by the user from the terminal via $ mygreatpackage (if installed with the -g flag with $ npm install -g mygreatpackage) or $ npx mygreatpackage when installed in the current project context, you need to supply an entry point to the executable in the bin field

{
  "name": "mygreatpackage",
  "version": "0.0.1",
  "description": "The best open source package available on the internets.",
  "bin": {
    "mygreatpackage": "./bin/mygreatpackage"
  }
}

5. Publish your package!

When you're satisfied with your package it's time to publish it to npm. This is as simple as running

$ npm publish

in your terminal! Assuming everything goes as planned, you should receive a confirmation from npm that your package was published! You should now be able to run $ npm install mygreatpackage from any other project and it will install your package in that project scope.

6. Package versioning after adding features and/or making changes

You will almost certainly make updates to your package and add (or even at some point remove) features. In order to publish your changes, npm requires you update your package version in package.json as you cannot publish over an existing version.

npm uses semantic versioning (semver) version numbering when publishing your package and it's likely not a bad idea to update your package versions based on the ideas from semver so your users can version your package in their projects in order to, for example ensure they always have the latest patch release of your package within the major and minor version to prevent installing breaking changes of your package in their project. You can use the following commands which npm will create a new commit of your package with the updated versions based on a couple helpful commands:

$ # update your package to a new major version
$ # 0.0.1 will become 1.0.0
$ # 1.0.0 will become 2.0.0
$ # 0.5.5 will become 1.0.0
$ npm version major
$
$ # update your package to a new minor version
$ # 0.0.1 will become 0.1.0
$ # 1.0.0 will become 1.1.0
$ # 0.5.5 will become 0.6.0
$ npm version minor
$
$ # update your package to a new patch version
$ # 0.0.1 will become 0.0.2
$ # 1.0.0 will become 1.0.1
$ # 0.5.5 will become 0.5.6
$ npm version patch

After you update the package version you can now republish, $ npm publish to publish the latest and greatest code to npm.

BONUS: scoped packages

If you have an npm organization where you'd like to publish all your packages to instead of just the global npm scope (which is the default), you can deploy scoped packages in the form of @your-org/package-name. This might be applicable if you are publishing privately scoped, closed source packages that you're using in several projects and want a single place to pull the latest code from, or even if you are publishing open source software and want it to exist within the scope of the organization for IP or other reasons.

By default scoped packages are privately scoped and not installable by anyone outside of the npm organization, but you can publish to a public scope which would treat it like any other npm package in terms of being able to install it. We won't discuss this in detail in this post, but maybe we'll talk more about it later! :)