ES2015 – Ready for development

There is no doubt ES2015 (formerly known as ES6) is one of the top technologies for the foreseeable future and it’ll shortly become a common keyword in front-end job descriptions. Even though browser support for the latest JavaScript update hasn’t been finished yet, you can start learning it by practice right away thanks to Babel syntax transpiler. Studying the specification can be certainly beneficial, but if drilling the material is a preferable method for you to acquire knowledge, Babel is the tool that you’re looking for. In this post I’m going to show how to prepare a basic development environment for ES2015 using Gulp and Babel with automatic source compilation. Enough for the introduction, let’s get the ball rolling.

Advertisement

Your first ES2015 script

I assume you already have the npm package manager installed on your machine, but if not, you should quickly catch up on the setup. After that, create a directory where you want to start your playground web application and run the following command to initiate the new project. The interactive tool will ask you several questions about application details like its name, version, license, etc. As the result, a package.json file with the project description will be created.

npm init

Now, let’s write our brand new ES2015 style code. We’re going to use a src/js directory to keep our JavaScript source files. Inside the folder, create a file called es2015-greeter.js with the content presented below. It’s a declaration of a class with one method written using the new syntax.

class ES2015Greeter {
   appendGreetings(element) {
      element.innerHTML += 'Greetings from the ES2015!';
   }
}

In another file called app.js write a self-executing arrow function which creates an object based on the previously declared type and calls its appendGreetings() method. That is our application startup script.

(() => {
   var es2015Greeter = new ES2015Greeter();
   es2015Greeter.appendGreetings(document.body);
})();

In the src directory make an HTML file called index.html that loads the above scripts. Try opening newly created document in your favorite browser.

<!DOCTYPE html>
<html>
    <head>
        <title>ES2015 Web Starter</title>
    </head>
    <body>
        <script src="js/es2015-greeter.js" type="text/javascript"></script>
        <script src="js/app.js" type="text/javascript"></script>
    </body>
</html>

If your browser supports used ES2015 features, you’ll see the greetings appended by the es2015Greeter object to the body of the HTML page. In another case, which is more interesting to us, the body will be empty. Our goal is to make the script executable also on browsers without support for new features and that’s where Babel comes in.

Basic setup for Babel 6 and Gulp 3

Babel transforms files written using the new syntax into code executable by all browsers which support the previous JavaScript specification. At the first glance it might look as an unnecessary complication. After all, we use dynamic languages to skip the compilation step. Yet, it’s a small price we need to pay for the possibility to play around with ES2015 before full browser support is completed. But as you’ll see, with a simple configuration we can make this step almost unnoticeable.

The first thing that we need is the Gulp command line interface required for running the build of our application. As you’re going to use it on every project built with Gulp, it’s recommended to install the interface on your machine globally.

npm install --global gulp-cli

Then, we need to fetch required packages for Gulp and Babel. Since they’re specific to the current project, we install them in the project locally as development dependencies.

npm install --save-dev gulp gulp-babel babel-preset-es2015

Having all basic requirements set up, we’re going to write configuration for the transpiler. Babel expects a file called .babelrc in the root directory of the project, which in our case will simply enable all ES2015 features provided by Babel.

{
  "presets": ["es2015"]
}

Now, we want to run Babel transformations using Gulp. For that purpose, we need to write another configuration script inside gulpfile.js, which also should be placed in the root project folder.

var gulp = require('gulp');
var babel = require('gulp-babel');

var Path = {
    JS_SRC: 'src/**/*.js',
    HTML_SRC: 'src/**/*.html',
    DIST: 'dist'
};

var Task = {
    COPY_HTML: 'copy-html',
    COMPILE_ES2015: 'compile-es2015'
};

gulp.task(Task.COPY_HTML, () => {
    return gulp.src(Path.HTML_SRC)
        .pipe(gulp.dest(Path.DIST));
});

gulp.task(Task.COMPILE_ES2015, () => {
    return gulp.src(Path.JS_SRC)
        .pipe(babel())
        .pipe(gulp.dest(Path.DIST));
});

gulp.task('default', [Task.COMPILE_ES2015, Task.COPY_HTML]);

The script describes how our previously created source files should be processed. The first two lines contain dependencies for the script. Below we have a declaration of file system paths and custom Gulp task names grouped accordingly in plain JavaScript objects. At the end of the file, there are three tasks which make use of above declarations. The COPY_HTML task simply copies all HTML files under the src directory into a dist folder which we’re going to use as the output for the whole build process. Normally, we would probably somehow process these files, e.g. minify HTML, but for the clarity of the example it’s beyond the scope of this post. The COMPILE_ES2015 task scans for all files ended with the .js extension under the src directory, runs Babel compilation on these files, and places the resulting output under the dist folder by maintaining the original directory structure. The default task, which is a reserved name, describes what should be done if no task name is specified when the Gulp build is run. In this case it executes both aforementioned custom tasks.

We’re ready to compile our ES2015 code. Run the Gulp build from the root project directory using the command line.

gulp

Since no task is provided in the command, this will run the default one. When the build is finished, go to the dist directory and open the copied index.html file in your browser. Congratulation! After compilation, your ES2015 code works in browsers without support for the new syntax. If you are curious about how your JavaScript code was processed by Babel you can check the output in the dist/js directory.

The ES2015 script is working

Babel automatic compilation

We can now use the new JavaScript syntax, but running the build manually every time a change is made to a file seems rather tedious and time-consuming.  Moreover, the build process all files, not only those which were updated. It definitely doesn’t look optimal for a day-to-day work environment. Fortunately, with a few modifications to the build we can facilitate the development process.

Gulp ships with the ability to observe changes on the working directory and rerun specified tasks. We’re going to add a new task to the gulpfile.js, which will monitor the state of JavaScript and HTML files in the src directory and automatically update the dist folder when necessary using the corresponding tasks created before.

gulp.task('hotswap', () => {
    gulp.watch(Path.JS_SRC, [Task.COMPILE_ES2015]);
    gulp.watch(Path.HTML_SRC, [Task.COPY_HTML]);
});

Use the following line in order to run the above task from the command line.

gulp hotswap

As long as the task is running the files in the dist directory will be updated whenever a modification occurs in src. However, this solution is still not perfect. When Gulp detects a change in one JS file, the whole COMPILE_ES2015 task is rerun, which means all JS files will be updated including these that aren’t changed. The same goes for HTML files. To tackle this problem we’ll use an additional Gulp plugin which can be installed using the command below.

npm install --save-dev gulp-changed

The gulp-change plugin allows intercepting a pipe in a task and continue its execution only with files that were changed since the last task completion. We need to modify the gulpfile.js file and make use of the installed plugin. Here is the full listing of the extended build configuration.

var gulp = require('gulp');
var babel = require('gulp-babel');
var changed = require('gulp-changed');

var Path = {
    JS_SRC: 'src/**/*.js',
    HTML_SRC: 'src/**/*.html',
    DIST: 'dist'
};

var Task = {
    COPY_HTML: 'copy-html',
    COMPILE_ES2015: 'compile-es2015',
    HOTSWAP: 'hotswap'
};

gulp.task(Task.COPY_HTML, () => {
    return gulp.src(Path.HTML_SRC)
        .pipe(changed(Path.DIST))
        .pipe(gulp.dest(Path.DIST));
});

gulp.task(Task.COMPILE_ES2015, () => {
    return gulp.src(Path.JS_SRC)
        .pipe(changed(Path.DIST))
        .pipe(babel())
        .pipe(gulp.dest(Path.DIST));
});

gulp.task(Task.HOTSWAP, () => {
    gulp.watch(Path.JS_SRC, [Task.COMPILE_ES2015]);
    gulp.watch(Path.HTML_SRC, [Task.COPY_HTML]);
});

gulp.task('default', [Task.COMPILE_ES2015, Task.COPY_HTML]);

All of the changes are highlighted. First, we added a variable for the newly installed plugin. Next, both COPY_HTML and COMPILE_ES2015 tasks ware extended by a step in which source files are monitored for changes to prevent unnecessary execution. In addition, the hotswap task name was moved to others to maintain consistency.

Now you can start the Gulp hotswap task once again and try updating the es2015-greeter.js file, for instance by altering the greet message. Next, reload the index.html file in your browser to verify the expected result. If you go to the dist/js directory and check the dates of last modifications for both script files, you’ll see they aren’t the same, which proves the build finally works as desired.

New syntax in old environment

The current situation with ES2015 reminds me the times when Java 8 was released. On the one hand, people were excited about new features, but on the other, they knew their working environment wouldn’t be updated so fast so they limited themselves only to read the list of upgrades. Similarly, some developers are skeptical of ES2015 now because it’ll take some time for browsers to catch up on the specification. While this is an undeniable fact, Babel allows us practicing the new syntax without waiting for official support. The transpiler should encourage more programmers to familiarize themselves with ES2015 right now and greatly facilitate the adoption of the new language features.

Facebooktwittergoogle_plusredditlinkedinmail
Advertisement