Risan Bagja

Working with ES2015 Modules

ES2015 has its own module system. To create a module simply use the export keyword. For example, we have a TaskCollection module stored on TaskCollection.js file like this:

// TaskCollection.js
export class TaskCollection {
  constructor(tasks = []) {
    this.tasks = tasks;
  }

  print() {
    this.tasks.forEach(task => console.log(task));
  }
}

If we want to use this TaskCollection module from another file, we can import it using the import keyword like this:

import { TaskCollection } from './TaskCollection';

let myTasks = new TaskCollection([
  'Learn Javascript',
  'Learn ES2015 Modules'
]);

Table of Contents

Exporting Multiple Modules within One File

The ES2015 modules allow us to export multiple modules within one file:

// Shape.js
export class Square {
  constructor(length) {
    this.length = length;
  }
}

export function getShapeList() {
  return ['Square', 'Circle'];
}

export const PI = 3.14;

And now to import those modules, we can do it like this:

import { Square, PI } from './TaskCollection';

Although we are allowed to export multiple modules on one file, it’s best that we only export one module per-file to keep it simple.

Exporting Module at The End of File

If you don’t like the export syntax in front of the statement, you can put it at the end of file:

class TaskCollection {
  constructor(tasks = []) {
    this.tasks = tasks;
  }
}

export TaskCollection;

Default Export

We can use default keyword to export a default module. It’s make sense to always use default export if it’s the only module on the file.

export default class TaskCollection {
  constructor(tasks = []) {
    this.tasks = tasks;
  }
}

And to import a default module we no longer need object destructuring syntax.

import TaskCollection from './TaskCollection';

If there’s another non-default modules we would like to import it, we can do it like this:

// TaskCollection.js
export default class TaskCollection {
  constructor(tasks = []) {
    this.tasks = tasks;
  }
}

export const foo = 'bar';

// To import it.
import TaskCollection, { foo } from './TaskCollection';

Rollup JS

ES2015 module is great, but currently it’s not supported on most browser, we still need a javascript module bundler, one of them is Rollup.js

Installing Rollup

Install rollup locally within your project directory:

$ yarn add rollup -D 

We can access Rollup executable file at: ./node_modules/.bin/rollup.

Bundling The Module

If we want to bundle up our javascript file that importing various modules, simply run the following command:

$ ./node_modules/.bin/rollup ./src/main.js -o ./dist/main.js -f=es

Note that with three-shaking feature, Rollup will smartly select and bundle up the required modules only.

Rollup Configuration File

We can also create a configuration file for Rollup, so we don’t have to specify a command line options every time we’re bundling up the file. Create a file named rollup.config.js:

export default {
  entry: './src/main.js',
  format: 'es',
  dest: './dist/main.js'
};

And now to bundle up the file using the defined configuration, use the following command:

$ ./node_modules/.bin/rollup -c

Next, we can add a scripts option within the package.json. So we can easily bundle up this js file with npm command: npm run build.

{
  "scripts": {
    "build": "rollup -c"
  },
}

Transpiling ES2015 Code with Rollup Buble Plugin

Note that Rollup will only bundle up the modules, but not converting the ES2015 code to the old ES5 standard. In order to transpile the ES2015 code, we need a Rollup plugin named Buble.

Install the rollup-plugin-buble plugin:

$ yarn add rollup-plugin-buble -D

Then update the rollup.config.js to register the buble plugin:

import buble from 'rollup-plugin-buble';

export default {
  entry: './src/main.js',
  format: 'es',
  dest: './dist/main.js',
  plugins: [buble()],
};

Now whenever we run rollup -c command to bundle up the modules, the output file will also be transpiled.

Transpiling ES2015 Code with Rollup Babel Plugin

If you still want to use Babel for transpiling the ES2015 code, there’s also a Rollup plugin for Babel. Simply install the plugin and the required Babel preset with the following command:

$ yarn add rollup-plugin-babel -D
$ yarn add babel-preset-es2015 -D
$ yarn add babel-plugin-external-helpers -D

Next create the .babelrc file:

{
  "presets": [
    [
      "es2015", { "modules": false }
    ]
  ],
  "plugins": [
    "external-helpers"
  ]
}

And finally update the plugins option with babel() instead:

import babel from 'rollup-plugin-babel';

export default {
  entry: './src/main.js',
  format: 'es',
  dest: './dist/main.js',
  plugins: [babel()],
};

Webpack

Rollup is fast and the output file is pretty clean. But there’s also Webpack with tons of features and big community.

Install Webpack

To install webpack locally, run the following command:

$ yarn add webpack -D

We can access the executable file at: ./node_modules/.bin/webpack.

Bundling The Module

To bundle up the javascript file with Webpack, run the following command:

$ ./node_modules/.bin/webpack ./src/main.js ./dist/main.js

Webpack Configuration File

We can also define the bundle options within the configuration file named webpack.config.js:

module.exports = {
  entry: './src/main.js',
  output: {
    filename: './dist/main.js'
  }
};

Now to bundle up the file with configuration file we can simply run:

$ ./node_modules/.bin/webpack

Or we can also specify the configuration filename like so:

$ ./node_modules/.bin/webpack --config webpack.config.js

We can add a scripts option within our package.json file for running the Webpack:

{
  "scripts": {
    "build": "webpack"
  },
}

Now we can use the npm run build command instead.

Transpiling ES2015 Code with Webpack Buble Loader

Similar with Rollup, the Webpack will not automatically transform the ES2015 code to the old ES5 standard. In order to do so, we can use Buble loader for Webpack.

First, install the Buble and its Buble loader for Webpack:

$ yarn add buble -D
$ yarn add buble-loader -D

Next update our webpack.config.js file to include the Buble loader.

module.exports = {
  entry: './src/main.js',
  output: {
    filename: './dist/main.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
		  exclude: 'node_modules',
        loader: 'buble-loader'
      }
    ]
  }
};

The loader term in Webpack is pretty similar with task in Gulp. Note that the test option is assigned with a regular expression which simply just look for the file with .js extension.

Transpiling ES2015 Code with Webpack Babel Loader

We can also use Babel loader instead of Buble to transpile the ES2015 code.

First install the required dependencies:

$ yarn add babel-core -D
$ yarn add babel-preset-es2015 -D
$ yarn add babel-loader -D

Next update our webpack.config.js file to use the Babel loader:

module.exports = {
  entry: './src/main.js',
  devtool: "cheap-module-eval-source-map",
  output: {
    filename: './dist/main.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: 'node_modules',
        loader: 'babel-loader'
      }
    ]
  }
};

Generating Source Map

We can generate a source map to make a debugging process easier, simply add devtool option within our webpack.config.js file:

module.exports = {
  entry: './src/main.js',
  devtool: "cheap-module-eval-source-map",
  output: {
    filename: './dist/main.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'buble-loader',
      }
    ]
  }
};

You can check various devtool values here: Devtool