Demystifying JavaScript, ES6 & Webpack in 2017 for Back-End Developers

Let me kick this off by holding my hands up and saying that I would not consider myself to be a front-end developer. However, with that being said, I wanted to share my experiences so far of developing with JavaScript in 2017 and hopefully give back something practical that you can use to help you on your journey down this winding and ever changing path that is front-end development.

If you’re not interested in the theory and want to dive right into the practical stuff, feel free to skip to A Practical Demonstration.

Preface — Who are you?

For those of you who have no idea who I am, let me give you a bit of background. My name is Tom Glenn and I’m a Software Developer based in Edinburgh, Scotland. You can get in touch with me on Twitter or checkout my GitHub to see what I’ve been working on lately.

I’ve spent the majority of my software development career (~9 years) as a back-end developer with a particular focus on the .NET stack. Sure, I started off as a geeky teenager writing simple websites in HTML using Notepad, with far more blinking paragraphs and scrolling marquees than I care to admit… and over the years I’ve dabbled with the likes of CSS, jQuery, Angular and other tools — but for all intents and purposes, I’m a back-end developer.

With that being said, I’m finding myself increasingly involved with and interested in the front-end development process as a whole. This has become especially apparent since the introduction of isomorphic JavaScript and technologies like NodeJS — where I finally started to see a real benefit to understanding and becoming proficient in JavaScript.

Since diving into NodeJS about a year ago and exploring frameworks such as Express, I have found myself venturing into the realms of the front-end developer and playing around with, admittedly outdated, things like Knockout and Angular, but more recently Vue and React.

This exploration into technologies like React lead to me discovering the wonderfully cryptic world of ES6+, transpilers, linters, bundlers, etc… and it is here where I would like to share some of the pains and frustrations I have encountered and hopefully be able to help some of you learn from and avoid them in the future.

Transpilers and Linters and Bundlers — Oh my!

So as a predominantly back-end developer, I’m used to writing my code in a monolithic (but much loved… I’m looking at you Visual Studio ❤) IDE, hitting Build and letting the compiler do all the hard work of verifying that A) my code isn’t broken and B) compiling it into an artifact that can run on the web (or desktop etc).

However, in the NodeJS world I’ve had to familiarize myself with a much more bare metal set of tools such as Atom and a console (shout out to cmder) to develop and run my applications. While this brings about its own set of quirks and complications, even though text editors like Atom are extremely extensible, it also makes it very apparent that I’ve been mollycoddled by my beloved IDE and tooling, with one button compilation, powerful debugging and profiling tools and insanely good productivity boosting plugins like ReSharper etc.

This is where the first pain point reared its head… Transpilation.

Say what now?!

Transpilation in this instance is the term used to describe transforming modern JavaScript (ES6+) into JavaScript that browsers understand (ES5).

When I first heard this term, I had images of an operating theater and extremely skilled surgeons talking in completely incomprehensible medical jargon… and that’s exactly how being around modern front-end developers felt to me for a long time.

For a good while I ignored this Pandora’s Box. I stuck to writing my back-end node apps and front-end code in good old ES5.

Hey, it works” I thought…

Why change it?

But increasingly I was hearing from friends and colleagues things like…

You really need to be using ES6+ if you’re going to start doing serious front-end development"…

Why?”, I would ask them.

I couldn’t understand why I would want to add unnecessary complexity to things that just worked. But, despite my skepticism, I decided to entertain the idea and plodded on my merry way to start adding ES6 into my next project.

As it turns out, ES6 brings a ton of awesome features and syntactical sugar to JavaScript, that in turn make it a hell of a lot easier (and IMO more enjoyable) — especially for back-end developers. With ES6 you now have access to things like real classes and inheritance, lambda functions and a whole host of other things we’re used to seeing in languages like C#, Ruby and Python.

Here’s the thing… You don’t just start writing in ES6 and everything works. No no no, see most browsers only support the version of JavaScript known as ES5.

That’s where transpilers like babel come into play. But in order to use babel to transpile your ES6+ code into ES5, you either have to run babel from the command line or integrate it into your development pipeline by using a bundler such as Webpack.

What the hell is a bundler?”, you might be asking… Yeah, that’s what I asked too.

In short, a bundler is a tool that processes your source files and “bundles” them together. As a back-end developer you can think of this as a sort of compilation process. It turns your myriad of source files into, usually, a single artifact (.js file) that you can then include on your web page.

It’s that processing step of the bundler that we can use to our advantage in order to allow our JavaScript code written in ES6+ syntax to be transpiled into browser-compatible ES5 syntax.

A Practical Demonstration

Let’s dive into an example of how you can use Webpack to transpile and bundle your JavaScript written in ES6+ into ES5 ready for inclusion in your website.

Before you begin, ensure you have NodeJS and NPM installed. You can verify this by running the following commands:

$ node -v
$ npm -v

You should see version numbers being output into your console. If you don’t, head over to nodejs.org and install the latest stable version.

To begin, let’s create a directory somewhere:

$ mkdir webpack-demo
$ cd webpack-demo

From here we need to initialize this as a Node package/app by running the following command:

$ npm init

Follow the prompts here, giving your package a name and some other meta data. You can just hit enter a few times to accept the defaults. This generates a package.json which will store meta data about our package, as well as what dependencies it has.

Inside the folder you just made, create an index.html file that includes the following.

<!doctype html>
<html>
<head>
<title>Webpack Demo</title>
</head>
<body>
<div id="app"></div>
<script src="app/index.js"></script>
</body>
</html>

We can see that this file is an extremely simple HTML file that includes a single div element called app and a reference to a JavaScript file which doesn’t exist yet — don’t worry, we’ll get to this later.

Next, we want to create a JavaScript file that uses ES6 syntax. Remember, most browsers don’t currently support ES6 natively, so we will need to transpile this file into ES5.

Let’s create a new folder called app for our raw source file to live.

$ mkdir app

Inside this folder, create an index.js file with the following contents:

import greeting from 'greeting'
class GreetingComponent {
constructor(el) {
el.innerText = greeting.random();
}
}
var greetingComponent = new GreetingComponent(document.getElementById(’app’));

This file uses the ES6 import syntax to import a JavaScript library called greeting and the class syntax to define an object that we can then instantiate. This simple class takes a dom element and inserts a random greeting message into it.

Go ahead and open your index.html file in a browser now and open the developer tools (F12 if you’re using Chrome).

What you’ll probably see is a completely blank page and a lovely error message that says this:

Uncaught SyntaxError: Unexpected token import

That’s because your browser doesn’t understand the ES6 syntax we’ve just written, and it needs to be transpiled…

So let’s do that!

We’re going to need to install some packages, so open your console and type the following:

$ npm install babel-core babel-loader babel-preset-env webpack --save-dev

and also:

$ npm install greeting --save

Woah! What’s all that?!”, you ask.

Don’t panic. What we’ve done here is install the transpilation tool Babel and the winner of the “bundler of choice award 2017" — Webpack. Oh, and we also installed the greeting package that we referenced earlier on.

Next we need to create a configuration file that tells Webpack what to do.

Create a file in the root of your project folder called webpack.config.js and enter the following:

module.exports = {
entry: './app/index.js',
output: {
filename: './dist/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
]
}
};

Let’s quickly break this file down.

First of all, we are defining the entry point of our application. This is the raw source file that Webpack should use to begin the bundling process. It will look at this file, and create a dependency tree based on imports and then bundle together all the required resources. In our case this should be the app/index.js file we created.

Next we define the output path for the bundled artifact that Webpack will create. Here we define that as dist/bundle.js.

The next part looks pretty complicated, but really all we are doing is telling webpack to run a module that looks at all .js files (excluding any in the node_modules folder) and transpiles them into ES5 using the babel-loader package that we installed earlier using the babel-preset-env preset (you can read about what this preset does here).

Next we need to go into our package.json file and define a script that will allow us to run this Webpack build.

Inside the scripts section add the following line:

"build": "webpack"

Next, open up the index.html file again and change the source of the script tag to the bundle we’re going to build.

<script src="dist/bundle.js"></script>

Finally, in the console, run the build script we just defined.

$ npm run build

You should see some lovely Webpack output here, with the key bit we’re looking for being:

Time: 593ms
Asset Size Chunks Chunk Names
./dist/bundle.js 4.43 kB 0 [emitted] main

The last step is to open up your webpage again in your browser. This time you should see no errors in the console and instead see a lovely greeting message in your browser window.

If you open /dist/bundle.js you will see that your original source file has been completely transformed with lots of cryptic looking module definitions and other bits I won’t even pretend to understand. This is the ES5 output of our script complete with all the required dependencies bundled together into a single file.

Congratulations, you’ve just successfully transpiled and bundled an ES6 application!

Go forth and bundle!

Now that you’ve conquered the mystical world of ES6, you’re free to go forth and explore the vast array of JavaScript libraries, frameworks, packages and tools with the confidence that the next time someone mentions ES6, transpilers or bundlers you know what they’re talking about!

I would highly advise you take a look into some of the popular front-end frameworks out there such as Vue and React.

If you enjoyed this post or found it useful, please let me know via Twitter or leave me a comment.

Thanks for reading!