How to Use ES6 for
Universal JavaScript Apps

Eric Elliott
Apr 28, 2015 · 4 min read

Now that the dust has settled a bit, I’m finally beginning to use ES6 for production apps — and because I write universal JavaScript, it has to work for both Node.js and browsers.

This won’t be an in-depth tutorial about ES6 features or universal JavaScript (aka isomorphic JavaScript). We’re just going to cover the basics to get you up and running.

Use Babel

Babel.js is a great tool that lets you transpile your ES6 code into ES5 code that runs in today’s JavaScript environments, including Node.js and browsers, but it isn’t obvious how to get it set up.


Install Babel

Nearly every tutorial you find will tell you to install Babel globally. That’s fine if nobody has to share your code, but if you’re on a team or producing open-source libraries, install it locally per-package, as well:

Now you can launch the `babel-node` CLI/REPL:

For Browserify workflows, you may need these, as well:

This will let you use all the cool new ES6 syntax, like arrow functions:

But it won’t let you use the new built-in methods like `Object.assign()`, `Object.is()`, etc…

This isn’t immediately obvious, because these features work great using the `babel-node` REPL:

Lucky for us, this is easily solved with a polyfill:

Then, at the top of your entry file:

Linting

Worried that you’ll have to give up linting your code? No worries. ESLint has you covered!



The ES6 love is in the `env` and `ecmaFeatures` keys. You’ll need those to prevent errors when ESLint encounters your ES6-specific code.

If you also want object rest & spread (an ES7 proposal commonly used in React code), you’ll also need `babel-eslint`.

Compiling

For most cases, you can simply replace your `node` calls with `babel-node` calls. `babel-node` caches modules in memory, so there’s a significant startup delay and potentially a lot of memory usage. Consider compiling to to ES5 for production. Read on.

Babel’s docs make compiling look like a breeze:

Couldn’t be easier, right? Well, if you don’t try to import any modules, sure, this will work fine. But if you do anything non trivial, you’ll want to compile your whole code base, not just one file. For that, you want to use the `-d` option.

Note that the output directory comes first.

If you want the debugger to work properly, you will want to add source maps with the `-s` option:

Doing so will tell Babel that for each file it compiles, it should also produce a source map file that will tell debuggers where to find the original source code while you’re stepping through the live code in the engine. In other words, you’ll see the code that you wrote, instead of the compiled output that Babel generated. That’s usually what you want.

To compile for the browser, you want to use Webpack, or the Babelify Browserify transform. I typically use babelify for quick compiles at the terminal. For instance, to run some unit tests:

  1. Install `browserify` and `browser-run` so that you can use them anywhere in your terminal.
  2. Create a bundle from `script.js` and run the script in chrome. Hit http://localhost:2222 from your favorite browser, and the script will run in the browser. Console log output will get piped back to the console.

Compile a bundle:

Configuring Webpack is too much for this quick tutorial, but if you want to skip all the busywork, you can use this boilerplate for production modules.

Using Existing Modules

Using the above mentioned tools, you can import both ES6 and Node-style modules using ES6 syntax:

So you can keep using all the standard modules you’ll find in the massive npm ecosystem in your modern ES6 codebase — but since so many people are still using ES5, I recommend that you publish compiled versions of your modules to npm.

For public libraries, I put the source in a `source` directory, and compiled ES5 in `dist` or `lib`. For now it’s probably a good idea to point to the compiled ES5 version with the `main` key in `package.json`.

Automation

I like to put these commands in my npm scripts:

React

Bonus for React users: you’re covered, too. Both Babel and ESLint support JSX. Nice!

EDIT: As of Nov 8, 2015, changes to the Babel 6 API have broken babel-react-transform. If you need it, you can install the latest compatible version of Babel:

Party Time

Congratulations! You’re ready to start using ES6 for your universal apps. In case you’re wondering, here are a few of my favorite ES6 things you should explore:

  • Compact object literals
  • Destructuring
  • Arrow functions (Great for one-line lambdas)
  • Default params
  • Rest params
  • Generators

You should memorize the new defaults/overrides pattern right now:


Enjoy!



Eric Elliott is the author of “Programming JavaScript Applications” (O’Reilly), host of the documentary film-in-production, “Programming Literacy”. He has contributed to software experiences for Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, and top recording artists including Usher, Frank Ocean, Metallica, and many more.

He spends most of his time in the San Francisco Bay Area with the most beautiful woman in the world.

JavaScript Scene

JavaScript, software leadership, software development, and…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store