Ungerboeck Digital - Blog

Blog

 

Gulp: Making Complex Builds Easy to Swallow

×

Warning

JUser: :_load: Unable to load user with ID: 235

Aug 29, 2016
Gulp tutorial

Let’s say you've got a web-based project using some some sweet new client-side tech. You've got Sass taking care of your style sheets (with a little Bourbon thrown in), maybe a handlebars or mustache handling your templating, multiple JavaScript libraries and custom modules you'd like minified for production, the works. Sounds pretty cool right? Well it is until it comes time to build the project.

You run a sass command to compile your stylesheets. You might run a seperate command to pre-compile some of your handlebars templates. And yet another to minify certain javascript files, but only sometimes for some of them because in certain environments you may need to debug others. This compilation process can become tedious pretty quickly especially since you must manually enter the commands each time you change a related file.

“Marlon,” you might say, “it would be great if I had an open source tool, built on the back of one of the most popular modern JavaScript environments out there with full package management that I can use to automate my builds.”

Well oddly specific web developer, you're in luck. That thing does exist and it's called Gulp.

Gulp is a kick-butt JavaScript build tool built on top of Node.js and this post is going to teach you how to get started with it.

First of all you'll need to install Node.js on your machine. To do so, go to https://nodejs.org/en/ and download the recommended package for your system. The Node.js install includes the Node Package Manager (npm) which is what you'll use to control your Gulp install as well as any complementary Gulp packages.

Once Node and npm have been installed you should create a package.json file in the root directory of your project. This file is recognized by npm as a description of all dependencies that should be included in your project. It's also very important to keep the dependency list in this file up to date with any packages you install locally since this is what other developers will use to update their environments in order to contribute to your project. An example of a package.json file that includes Gulp is shown below.

{
  "name": "Test App",
  "version": "1.0.0",
  "description": "An app that uses npm",
  "author": "Some Cool Guy",
  "dependencies": {
    "gulp": "3.9.1"
  }
}

Once you've created your package.json file, navigate to it's directory and run `npm install.` This will tell npm to look at our package.json file and install all of the dependencies we've listed. You'll notice that these dependencies have been added to a folder called “node_modules” in the base directory. Pretty neat, huh? Well, not really. Not yet anyway. All we've done so far is install Gulp locally, but you gotta start somewhere. Let's test it out by creating a basic gulp file.

var gulp  = require('gulp');

gulp.task('default', function () {
  console.log('woohoo!');
});

Save this file as “gulpfile.js” in the same directory as you package.json file. Congratulations, you did it! To check it out run `gulp.`

You'll see that Gulp reports that it's using the gulpfile.js we defined. It starts the 'default' task we defined within that file, logs “woohoo!,”and reports that the default task has finished. That's all well and good, but since I don't want this to be the most boring tutorial you've ever read let's spice things up a bit. Say we wanted Gulp to compile some Sass with some Bourbon and Neat thrown in because we're hip like that. Open that same gulpfile.js and modify it so it matches mine below.

var gulp  = require('gulp');
var sass  = require('gulp-sass');
var sourcemaps  = require('gulp-sourcemaps');
var plumber = require('gulp-plumber');
var bourbon = require('node-bourbon');
var neat = require('node-neat');

gulp.task('sass', function () {
  gulp.src('./sass/**/*.scss')
    .pipe(plumber())
    .pipe(sourcemaps.init())
    .pipe(sass({
      includePaths: require('node-bourbon').includePaths,
      includePaths: require('node-neat').includePaths
    }).on('error', sass.logError))
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('./site/css/'));
});

gulp.task('default', ['sass'], function () {
  gulp.watch('./sass/**/*.scss', ['sass']);
});

Now we're talking. Things are starting to look a little more interesting. You'll notice, though, that if you try to run our `gulp` command now you'll get an error. This is because we have yet to install all the packages we just included in our gulpfile. Now we could go back to our package.json file and add all those packages and their versions to our dependencies list and run `npm install` again, but why do that when there's a nifty one-liner we can use to do that for us? Run the following command:

npm install -S gulp-sass gulp-sourcemaps gulp-plumber node-bourbon node-neat

This will tell npm to install all the specified packages with the “save” flag. This flag will automatically add the installed packages as dependencies in our package.json file. See for yourself. Our file should now look like the following:

{
  "name": "test_app",
  "version": "1.0.0",
  "description": "An app that uses npm",
  "author": "Some Cool Guy",
  "dependencies": {
    "gulp": "^3.9.1",
    "gulp-plumber": "^1.1.0",
    "gulp-sass": "^2.3.2",
    "gulp-sourcemaps": "^1.6.0",
    "node-bourbon": "^4.2.8",
    "node-neat": "^1.7.2"
  }
}

Ok, that actually is pretty cool. Before we run anything, though, let's step through our new gulpfile so we can tell what the heck is going on.

var gulp = require('gulp');

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

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

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

var bourbon = require('node-bourbon');

var neat = require('node-neat');

The above loads and instantiates all of the packages we just installed, but I'm sure you could figure that out.

gulp.task('sass', function () {

gulp.src('./sass/**/*.scss')

   .pipe(plumber())

   .pipe(sourcemaps.init())

   .pipe(sass({

     includePaths: require('node-bourbon').includePaths,

     includePaths: require('node-neat').includePaths

   }).on('error', sass.logError))

   .pipe(sourcemaps.write())

   .pipe(gulp.dest('./css/'));

});

Here's the meat of our code, but what does it do exactly? We've defined a task called 'sass' that then goes on to do a bunch of weird stuff. Luckily it's much more straight-forward than it looks.

First of all we call

gulp.src('./sass/**/*.scss')

This tells gulp that we'd like this task to look for all .scss files within the sass folder or any of its child folders.

After that the magic starts. One of the greatest things about gulp is its ability to pipe the output of one command to another as input, just like you would with the | character in the terminal. As you might have guessed, that's exactly what we're doing here.

We start with

.pipe(plumber())

which passes the contents of the specified source files through a handy plugin that makes sure that our pipeline doesn't break should it encounter errors in any other gulp plugins.

The output of this command is then sent to

.pipe(sourcemaps.init())

which tells gulp that the output of the following commands are intended to be written to a sourcemap. If you're not familiar with sourcemaps, I highly suggest you check them out. Basically, they're a way for you to get the performance gains of compressed files without all the debugging hassles. That's a little out of scope for this tutorial, but a nice in-depth explanation can be found here.

Once we initialize our sourcemap we use

.pipe(sass({

     includePaths: require('node-bourbon').includePaths,

     includePaths: require('node-neat').includePaths

   }).on('error', sass.logError))

to tell the sass plugin to look at our Bourbon and Sass paths to resolve any @import declarations we may have (and log any errors should they occur).

To write these commands to our sourcemap we use

.pipe(sourcemaps.write()).

Finally, we pipe all of this through

.pipe(gulp.dest('./css/'))

to let gulp know we want our compiled files to end up in the css folder.

And that's all she wrote! With this task we've done a lot of quite complicated things in very few lines of code. Keep in mind that this does assume you've already installed Bourbon and Sass on your machine since we are just installing the related node packages (if you haven't the instructions to do so are here and here, respectively.

After all this you can now create a “sass” folder, fill it with sassy style goodness to your heart's content and run the `gulp sass` command. This will compile all of your files to css and place them in the css folder just like we wanted. Sweet!

Oh, and I almost forgot our final chunk of code:

gulp.task('default', ['sass'], function () {

gulp.watch('./sass/**/*.scss', ['sass']);

});

This will set our default gulp task to watch for sass changes and automatically rerun our 'sass' command. No more worrying about manually compiling each time, you now have a tiny js servant to do it for you.

So, you just got done stepping through our basic example and you already have a million ideas on how to improve your build process with Gulp? Well you're in luck, there's probably a package for that! Currently there are about 2600 gulp plugins in the official plugin registry that do everything from pre-compiling handlebars to picking your nose. And if you don't like any of those, it's all open source. Just make your own.

Let's Talk

Looking to know more? Drop us a note through the form below.

636.300.5606  |  100 Ungerboeck Park, O'Fallon, Missouri, 63368
Godzilla