Modern Web Best Practice: Build Tools

Aaron delves into build tool functionality and outlines things to consider when selecting a build tool.

Introduction

In this post I’m going to discuss the importance of build tools and how they make your job easier by automating tasks for you. Whether you build small HTML and CSS-driven websites or large JavaScript applications, a build tool can greatly improve your workflow. There are many options out there, but I’ll discuss two of the most popular ones we use at appendTo and why you might choose one over the other.

What is a build tool?

What exactly does a build tool do? In simplest terms, a build tool automates the time-consuming, repetitive tasks in our workflow so we don’t have to do them manually.

An example of this could be compressing your CSS any time you make a change to a CSS file in your code. Manually compressing this code would be very tedious and could lead to human error if we worked with multiple people. It would be better if this process was handled automatically.

This is precisely what a build tool does. It automates tasks to save us time and effort.

Grunt and Gulp

There are many build tool options for nearly every coding language. However, the two that I’ll specifically talk about in this post are Grunt and Gulp, two JavaScript-based build tools.

Why JavaScript-based build tools?

You might be wondering why we’re using JavaScript-based build tools. We’re using JavaScript because it is an incredibly popular language on the web, it’s very quick, and it’s easy to find helpful resources for both Grunt and Gulp.

Grunt

Maturity

One benefit that Grunt has over Gulp is that it is a more mature build tool. The first commit on the Grunt repository is dated September 2011, while Gulp’s first commit is dated July 2013. While an older tool doesn’t necessarily mean it’s better, it has given the community time to build a robust database of documentation, plugins, and troubleshooting.

Large plugin library

The Grunt community has built a huge library of plugins – well over 3,000 as of this post. Because the library has had time to grow, it’s extremely rare to run into a problem that hasn’t already been solved through an existing plugin. However, Grunt does thorough API documentation if you find yourself needing something more custom.

Synchronous vs. asynchronous tasks

Grunt tasks (by default) are synchronous while Gulp tasks are asynchronous. Depending on your needs, either one of these methods could be a good thing. It’s simply important that you know how the build tool is going to work so you don’t get confused when your compiling doesn’t work properly.

For example, suppose you have a “clean” task (a task that empties out a directory) and it needs to occur before a “copy” task. If your tasks are synchronous, the clean task would run first and then the other would follow. However, if your tasks are asynchronous, you may run into issues because the build tool will attempt to run these tasks simultaneously.

Again, this is not a pro or a con for either build tool. In fact, both tools can run synchronous and asynchronous tasks. It’s simply important you understand how they work by default.

Gulp

Streams

As stated earlier, Gulp tasks run asynchronously as opposed to Grunt’s synchronous workflow. There is a significant advantage when running tasks asynchronously: speed. Because all tasks run concurrently, you’ll notice that Gulp runs extremely quick when firing events. This is all thanks to Node and the power of streaming.

As mentioned above, there may be times where you need to run tasks synchronously as opposed to asynchronously. Gulp allows you to setup dependent tasks in case you need to ensure Task A occurs before Task B.

Task piping

Another advantage of Gulp over Grunt is the use of task “piping”. This makes file handling – as well as your Gulpfile – much simpler and terse. If you wanted to concatenate and minify your JavaScript with Grunt, you’d need to first concatenate your files into a single temporary file. This temporary file is what getsfed into the minification process.

However, Gulp uses task piping so files are seamlessly pushed from one task to another. This eliminates the need to create these temporary files and you might see this written as:


var gulp = require('gulp'),
    coffee = require('gulp-coffee'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify');

gulp.task('scripts', function() {
    return gulp.src('js/*.coffee')
    .pipe(coffee())
    .pipe(uglify())
    .pipe(concat('all.min.js'))
    .pipe(gulp.dest('build/js'));
});

You can see from the example that all of our CoffeeScript files get piped into a CoffeeScript compiler, then through uglification, then concatenated into an all.min.js file and placed within build/js. This all happens without creating temporary files as we move through the scripts task.

Grunt or Gulp?

There’s really no clear choice as to which build tool “wins out”. Both of these frameworks are well-made, reliable, and have pros and cons on both ends. You may favor Gulp for one project and Grunt for another. Your decision is all about deciding which tool is best for the project at hand.

You’ll rest easy thanks to the great communities behind both tools as well as a plugin library to fulfill nearly any need you have.

Previous

Building a Command-Line Reporting Task with JavaScript and Wakanda

AngularJS: One Step at a Time

Next