Gulp – Build Automation for Javascript

Tired of restarting your server manually, over and over again, whenever you change something? Straining under the labor of recompiling your Less / Sass dozens of times an hour? No more. Let a robot do it for you. A robot named Gulp.

Why Gulp?

First off, I should mention that there are several build automation tools written specifically for Node.js apps. Grunt is probably the most popular, but there’s also Jake and a couple others. I started with Grunt, but I’m liking Gulp more and more as I use it. It’s faster, more flexible, and just “feels” more intuitive and straightforward.

basedHonestly, though, which one you use isn’t important. All that’s important is that you use SOME KIND of build automator / task runner. Over the long run, it will save you hours of repetitive, frustrating, mindless drudgery. Sound good? Read on.

Installing Gulp

To use Gulp in your app, you must install it globally onto your system, as well as locally in your project directory. Use the following commands in terminal, while inside your project dir:

npm install --global gulp
npm install --save-dev gulp
touch gulpfile.js

Your First Gulp Task

Open the gulpfile.js you just made in a text editor and put in the following:
var gulp = require('gulp');
gulp.task('default', function() {
  console.log('If you can read this, gulp is working!');
});

Go back into your terminal, type gulp, and press Enter. You should see the following output:

[20:33:59] Using gulpfile ~/YourProjectFolderHere/gulpfile.js
[20:33:59] Starting 'default'...
If you can read this, gulp is working!
[20:33:59] Finished 'default' after 74 μs

So what happened here? We created a task called default in the gulpfile, which calls a function when the task is run. That function then performs a console log. Using the gulp command with nothing after it will run any task named default. It’s a good idea to always have a default task that does the important work of building and running your project. That way, anybody else who has to work with your project can just type gulp in the terminal and see it run without having to paw through your code.

Your First Useful Gulp Task

So that was fun, but not particularly worthwhile. Let’s do something useful with Gulp!

Let’s say you have a directory full of JavaScript files, a directory called ‘js’. All these files need to be copied over to a directory called ‘build’ before you can publish your app. No problem! Put this into your gulpfile:

var gulp = require('gulp');

gulp.task('copy-js', function () {
  gulp.src(['js/**/*.js'])
    .pipe(gulp.dest('build'));
});

gulp.task('default', ['copy-js']);

There’s a lot going on here, so I’ll explain bit-by-bit:

  • We created a new task called copy-js, which will do all our copying for us.
  • The first line inside that task, beginning with gulp.src, tells gulp where to look for the files we want to copy. That bunch of /s and *s we gave it is a pattern-matching string called a glob. Here’s how to interpret this glob:
    • The js/ part tells gulp to look inside the directory named ‘js’.
    • The **/ part tells gulp to look inside any subdirectories within the ‘js’ directory.
    • The *.js part tells gulp to find all files that end with the .js file extension.
  • On the next line, we chain a method onto the end of gulp.src… specifically, the .pipe() method. .pipe() takes the output of the previous method (i.e., the .js files we found) and lets us use it as input for another method, just like a unix pipe. This is extremely useful, as you’ll soon see.
  • .pipe() passes the files we found to gulp.dest(‘build’)gulp.dest() is used to save files to a particular location. Which location? Why, the one we told it: the ‘build’ directory.
  • Finally (and importantly!) we changed the default task. Instead of executing a function, default will now execute a list of sub-tasks. For now, we just want it to execute our copy-js task.

Now, if you type gulp into the terminal, any JavaScript files in the ‘js’ directory will be copied into the ‘build’ directory. Gulp will even create a ‘build’ directory for you if it can’t find one. How thoughtful!

Watch This

“This is all well and good,” you might be thinking, “but how does this actually save me time?” After all, you still have to keep typing gulp into the terminal every time you want this copy and paste to happen, right?

The answer is no, you don’t. Gulp can run tasks for you, automatically. Enter gulp.watch():

var gulp = require('gulp');

var jsDir = 'js/**/*.js';

gulp.task('copy-js', function () {
  gulp.src([jsDir])
    .pipe(gulp.dest('build'));
});

gulp.task('watch-js', function () {
  gulp.watch(jsDir, ['copy-js'])
    .on('change', function (event) {
      console.log('File ' + event.path + ' was ' + event.type);
    });
});

gulp.task('default', ['watch-js']);

Ok, so what happened here?

  • We made a new task called watch-js. When this task is executed, gulp.watch() will keep a close eye on the directory we tell it, watching for files inside to change. When they do, the tasks in the array we provide will be executed… in this case, the copy-js task.
    • To put it simply, whenever we change a .js file, it’ll be copied over automatically. How cool is that?
  • We chained .on() to the end of gulp.watch(). This lets us execute code when certain conditions are met. In this case, when a file changes, we execute a function. This function uses the event parameter to let us console log which file changed, and how it was changed (added, changed, deleted, etc.)
  • Also, we put the JavaScript directory glob into a separate var called jsDir, which we use in both the copy-js and watch-js task. That way, we can make sure it stays consistent.
  •  Finally, we change the default task to execute watch-js when it’s called. By the way, you’ll notice this is an array; we can comma-separate multiple sub-task names to be called here, if we choose.

Sweet! What Else?

Gulp can help you automate all kinds of development-related tasks, including but not limited to:

  • Linting
  • Unit / Integration Testing
  • Bundling / Concatenation
  • Minifying / Compression
  • CSS pre-processor compilation (i.e. Sass / Less)
  • Image resizing / processing
  • Asset versioning
  • Running shell commands

To learn more, check out Gulp’s documentation and browse their extensive, searchable list of plugins. To use a plugin, npm install it, require it at the top of your gulpfile as a variable, and then use it based on the plugin’s documentation. Like the following example does with gulp-sass:

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

gulp.task('default', function() {
  gulp.src('sass/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('css'));
});

That should be enough to get you started. Happy gulping!

Leave a Reply

Your email address will not be published. Required fields are marked *