Blog

Publishing ES6 code to npm

22 Sep, 2015
Xebia Background Header Wave

This post is part of a series of ES2015 posts. We’ll be covering new JavaScript functionality every week!

Most of the software we work with at Xebia is open source. Our primary expertise is in open source technology, which ranges our entire application stack. We don’t just consume open source projects, we also contribute back to them and occasionally release some of our own. Releasing an open source project doesn’t just mean making the GitHub repository public. If you want your project to be used, it should be easy to consume. For JavaScript this means publishing it to npm, the package manager for JavaScript code.

Nowadays we write our JavaScript code using the ES6 syntax. We can do this because we’re using Babel to compile it down to ES5 before we run it. When you’re publishing the code to npm however you can’t expect your package consumers to use Babel. In fact if you’re using the Require Hook, it excludes anything under node_modules by default and thus will not attempt to compile that code.

Babel setup

In order to use Babel in our project, we need to configure it to be useful. This is commonly done using a .babelrc file, which is essentially JSON formatted:

{
  "plugins": ["transform-runtime"],
  "presets": ["es2015"]
}

Babel will automatically look for the .babelrc file for its configuration, but it can also be configured through package.json. In this example we configure Babel to use the transform-runtime plugin (see below) and use the es2015 preset, which allows us to use ES2015 (ES6) syntax in our code.

Prepublish

The reality is that we have to compile our code to ES5 before publishing to npm, which is what people writing libraries in CoffeeScript have been doing for a long time. Luckily npm provides a helpful way to automate this process: the prepublish script. There’s a whole list of scripts which you can use to automate your npm workflow. In package.json we simply define the scripts object:

{
  "name": "my-awesome-lib",
  "version": "1.0.0",
  "scripts": {
    "compile": "rimraf lib/* && babel src -d lib",
    "prepublish": "npm run compile"
  },
  "main": "lib/index.js",
  "dependencies": {
    "babel-runtime": "^6.11.6"
  },
  "devDependencies": {
    "babel-cli": "^6.11.4",
    "babel-core": "^6.13.2",
    "babel-preset-es2015": "^6.9.0",
    "rimraf": "^2.5.4"
  }
}

This will make npm automatically run the compile script when we run <em class="markup--em markup--p-em">npm publish on the command line, which in turn empties the ./lib directory and triggers babel to compile everything in ./src to ./lib (the de-facto standard for compiled sources in npm packages, originating from CommonJS). Finally we also define the main entry point of our package, which denotes the file to import when require(‘my-awesome-lib’) is called.

An important part of the configuration is the runtime transform. By default Babel will include helper functions such as _extend in every file that needs them, leading to these functions to be defined time and time again. The runtime transform plugin replaces these with require calls to the babel-runtime package, which has to be a regular dependency for that reason.

Ignoring files

It’s easy to simply publish all of our source code to npm, but we don’t have to. In fact it’s much nicer to only publish the compiled sources to npm, so package consumers only have to download the files they need. We can achieve this using a file called .npmignore:

*
!lib/*

This file is very similar to .gitignore, in fact npm will fall back to .gitignore if .npmignore is not present. Since we probably want to ignore ./lib in our git repository because it holds compiled sources, npm would normally not even publish that directory, so we have to use .npmignore to get the desired result. However if you want your library to also be directly consumable via a git URL you can commit ./lib to git as well.

Publishing

Now that everything is set up, the only thing left to do is publish it. Well, not so fast. First we should specify our version number:

npm version 1.0.0

This will update package.json with the new version number, commit this change to git and make a git tag for v1.0.0, all in one go. This of course assumes you’re using git, otherwise it will just update package.json. An even better way is to have npm automatically determine the next version number by specifying the scope of change. We should also specify a commit message:

npm version patch -m "Bump to %s because reasons"

For more options check out the npm documentation. Now finish up by pushing your new version commit and tag to GitHub and publish our package to npm:

git push --follow-tags
npm publish
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts