Using Rollup.JS to create JS modules

Using Rollup.JS to create JS modules and libraries is easy, it can easily output AMD, CJS, ES, IIFE and UMD JS formats with minimal configuration. Its plugin structure really nice too, you should find nearly anything you need here.

This post will focus on building a lodash style library. The output of the JS bundle will be supported by both ES5 and ES6 syntax just like lodash.

Skip to finished GitHub project here.

Basic Setup

Add Rollup.JS dependencies.

yarn add --dev rollup rollup-plugin-babel babelrc-rollup babel-preset-env

Add src/alpha.js file.

export function sayName(name) {
  console.log(`Your name is ${name}!`);
}

Add rollup.config.js file.

import babel from 'rollup-plugin-babel';
import babelrc from 'babelrc-rollup';

const babelConfig = {
  'presets': [
    ['env', {
      'targets': {
        'browsers': ['last 2 versions']
      },
      'loose': true
    }]
  ]
};

export default {
  entry: 'src/alpha.js',
  format: 'umd',
  moduleName: 'Alpha',
  sourceMap: true,
  plugins: [
    babel(babelrc({
      addExternalHelpersPlugin: false,
      config: babelConfig,
      exclude: 'node_modules/**'
    }))
  ],
  dest: 'dist/bundle.js'
};

Update package.json to look like this.

{
  "scripts": {
    "build": "rollup -c"
  },
  "devDependencies": {
    "babel-preset-env": "^1.4.0",
    "babelrc-rollup": "^3.0.0",
    "rollup": "^0.41.6",
    "rollup-plugin-babel": "^2.7.1"
  }
}

Rollup Watch

Getting Rollup.JS to watch your files is really easy, run this.

yarn add --dev rollup-watch

And then add this to your scripts in package.json.

"start": "rollup -c -w"

Now when you run this command Rollup.JS will watch for changes and build you module.

yarn start

Babel

I'm using babel-present-env here for the babel configuration, this is essentially becoming the autoprefixer of the JS world!

I'm also using babelrc-rollup here as not to conflict with the same .babelrc file when running with Jest for testing. Rollup.JS requires modules: false in the babel config to disable JS ES6 transformations but Jest needs those transformations to run tests on ES6 code.

Testing

Add Jest to do the testing, its very quick to get started with Jest and includes some great features outside of the box. Including great defaults with zero-configuration, mocks, coverage and no requirement on babel-register dependency like mocha.

yarn add --dev jest

Add .babelrc file to allow Jest to run against ES6 code.

{
  "presets": ["env"]
}

Add test/alpha.spec.js file.

import * as Alpha from '../src/alpha';

describe('#sayName', () => {
  beforeEach(() => {
    jest.spyOn(console, 'log');
  });

  afterEach(() => {
    console.log.mockRestore();
  });

  it('should say your name', () => {
    Alpha.sayName('Test');
    expect(console.log).toHaveBeenCalledWith('Your name is Test!');
  });
});

Add this to your scripts in package.json.

"test": "jest"

Now you can run the tests with.

yarn test

Usage

By specifying our output JS format as "umd" in the rollup.config.js we can support both ES6 and ES5 syntax in one file. Example usage of the JS module.

// ES6
import { sayName } from 'Alpha';
sayName('Tyrion');

// ES5
<script src='./bundle.js'></script>
Alpha.sayName('Tyrion');

Conclusion

Rollup.JS makes JS modules and libraries really easy to develop, test and ship. Webpack can no doubt do the same but with a bit more configuration. React has recently moved to Rollup.JS, Vue uses it and many other libraries are using it too.

Next time you come to write a JS module, take a look at Rollup.JS! It also plays nicely with Gulp too, see official documentation here or this project which creates a wrapper around Rollup.JS so it can use Gulp streams.

GitHub Project that this post is based on.

References