Using ES6 Modules with Webpack


ES6 is here, and it comes with modules. I found the syntax cool. As experiments widen our horizons and they are often fun, I thought I would share my learnings with you. If you would like to follow the steps below, feel free to do so. In this short tutorial, you will learn how to write a simple ES6 module, and how to run this code using Webpack.

In order to save you time, I uploaded each step of the tutorial on my GitHub account. Fork it from here!

Motivation

Even though I have been a RequireJs user for years, I was not completely satisfied with it. Coming from a Java background, I never liked the solutions ES5 offered for encapsulation, packaging and information hiding. Implementing the module pattern in Vanilla Javascript is one option, using the additional abstraction layer provided by RequireJs is another.

RequireJs and its plugins worked very well for me, therefore I didn’t feel much temptation to challenge my setup until modules got finalized in the ES6 specification. In my article Functional Programming with ES6, I re-iterated the popular belief of the linguistic time travel: transpilers such as BabelJs make it possible for you to use the expressive power of ES6 here and now. Getting rid of your old module loader and the ability to use ES6 modules may both be important factor in deciding to use ES6.

Last, but not least, if you consider writing complex web application logic without using the module pattern, please think again as your decision may backfire one day. Maintainable code is modular.

The Task

We will create an ES6 module representing a financial account. We will store transactions belonging to the account in an array. Each transaction has the following attributes:

  • amount : Integer in cents. Don’t even think about floating points! Depositing 0.1 then 0.2 won’t give you 0.3 as a result. If you don’t believe me, visit 0.30000000000000004.com;
  • date : String in "yyyy-MM-dd" format. We will simplify things. If you feel like experimenting with the Date object or you just want to laugh a bit, read my post on Javascript dates!

We will import this ES6 module in another file, fill it with some data for demo purposes, and populate an ordered list with the three largest transactions.

Step 1: index.html

Create a folder for this experiment and place an index.html file in it with the following contents:

The file myaccount.dist.js does not exist yet. We will use Webpack to create it.

Commit: 283488b.

Step 2: Configuring Webpack

If you don’t yet have Webpack, install it as a global Node module:

Webpack does not support the ES6 syntax by default. At the time of writing this post, there are still fewer ES6 module loader implementations around than Javascript frameworks, but the solutions are rapidly growing. We will stick to babel-loader in this tutorial. Let’s install it!

Now that Webpack is available, let’s create a configuration file webpack.config.js.

Our entry point src/main.js will be created shortly. All dependencies specified in this file will be copied to myaccount.dist.js recursively. Babel-loader is also invoked, transpiling all Javascript files it finds.

Commit: f0ffab1.

Step 3: Account module

In order to process transactions, we need an Account class. We will use the class syntax of ES6 to write the code. A short explanation will follow the example. Before reading the explanation, try to figure out what the code does.

Save the above code in src/Account.js. We will also need UnderscoreJs as it’s defined as a dependency. Grab it using

The code works in the following way:

  • We import the sortBy and first functions from the Underscore funcional programming utility belt
  • When creating an account with the new operator, we initialize the transactions to []
  • For the purpose of demonstrating how to import Underscore functions, we derive the top 3 transactions using Underscore functions. After sorting the transactions based on descending absolute transaction amount, we take the first 3 elements from the list. If you need more info on UnderscoreJs, I suggest this post
  • Depositing and withdrawing are both straightforward: we push a new transaction object to the transactions array, setting its amount and date

Commit: 37cce10.

Step 4: Create the entry point

The last missing file is src/main.js. We will import the Account class, create an account, add a couple of transactions and finish this step by displaying the top 3 transactions. We don’t need jQuery.

Commit: b9f00f5.

Step 5: Compile and run the application

Enter webpack in your terminal to run all the tasks specified in Step 2 and observe that the process should run without errors. Alternatively, if you would like to continue developing this demo and you don’t want to bother executing Webpack after each and every change, use the --watch switch.

Once myaccount.dist.js is created, view it in a browser window.

More tasks

This tutorial served its purpose by getting you started with ES6 modules and Webpack. If you like this setup, you can continue your experimentation from here. I will give you a couple of hints on how to continue:

  • Display the Account Balance
  • Format the amount strings so that they appear in dollars/euros or any other currencies, not cents
  • Derive a credit account and a debit account from the Account class. A credit account has a fixed credit limit, while a debit account does not allow withdrawals if the balance became negative
  • Experiment with ES6 templates to generate the top transactions
  • Use BackboneJs, React or any framework/library and apply separation of concerns. Check out how you can use modules with your setup

Anything is possible. The more you experiment, the better you become in the long run.

  • gotofritz

    How do you handle minification and sourcemaps? It’s where everything is falling flat for me at the moment.

  • You don’t have to set anything up. All you need is the -p switch for minification and the -d switch for generating source maps. I executed

    webpack -p -d

    on my code (see the Fork button above), and both Chrome and Firefox displayed the generated source maps properly.

  • Rolograaf

    Nice tutorial, I believe this is how the future of Javascript programming will look like?

    Cannot help to boast my solution to one of your tasks in the end.

    made a file lib.js which I called from main.js with
    “import * as lib from ‘./lib’;”

    and changed your format rule in
    ” + lib.ct2eur(transaction.amount) + ‘ (‘ + lib.day2date(transaction.date) + ‘)’;

    let me now if it can be refactored better…