Tutorial

Automate Your Tasks Easily with Gulp.js

Draft updated on Invalid Date
    Default avatar

    By Justin Rexroad

    Automate Your Tasks Easily with Gulp.js

    This tutorial is out of date and no longer maintained.

    Introduction

    As developers, we often need to look at the tools we use and decide if we are using the right tool for the job. Chris did an awesome write-up on Grunt early last year. But maybe Grunt just isn’t right for you.

    Gulp is a streaming build system, by using node’s streams file manipulation is all done in memory, and a file isn’t written until you tell it to do so.

    Much like Grunt, Gulp is a JavaScript task runner. Gulp however prefers code over configuration. Being that your tasks are written in code, gulp feels more like a build framework, giving you the tools to create tasks that fit your specific needs.

    Installation

    Gulp is easy to get installed and running. The steps are:

    1. Install Gulp Globally
    2. Install Gulp In devDependencies
    3. Create a gulpfile.js

    The first step is to get gulp installed globally.

    1. npm install --global gulp

    After that, you’ll need gulp as a devDependencies on any of your projects you want to use it in. Make sure that you have your package.json created by manually creating it or typing npm init. Once you have your package.json, let’s install gulp into devDependencies with:

    1. npm install --save-dev gulp

    And finally, you’ll need a gulpfile.js in your project root that contains your tasks. As an intermediary step, we’ll add the gulp utilities plugin so we have a runnable task that visibly shows it executed.

    1. npm install --save-dev gulp-util

    In the gulpfile.js file that you just created, we’ll make a simple gulpfile that just logs that gulp is running.

    gulpfile.js
        // grab our gulp packages
        var gulp  = require('gulp'),
            gutil = require('gulp-util');
    
        // create a default task and just log a message
        gulp.task('default', function() {
          return gutil.log('Gulp is running!')
        });
    

    And if everything went as expected running gulp in your command line should give you output similar to.

    1. gulp
    Output
    [12:32:08] Using gulpfile ~/Projects/gulp-scotch-io/gulpfile.js [12:32:08] Starting 'default'... [12:32:08] Gulp is running! [12:32:08] Finished 'default' after 1 ms

    Overview

    Directory Structure for this Tutorial

    We should probably take a second to define our project’s structure. For this simple demo, we’ll use the following structure, you can leave the files blank for now.

        public/
          |  assets/
          |  |  stylesheets/
          |  |  |  style.css
          |  |  javascript/
          |  |  |  vendor/
          |  |  |  |  jquery.min.js
          |  |  |  bundle.js
        source/
          |  javascript/
          |  |  courage.js
          |  |  wisdom.js
          |  |  power.js
          |  scss/
          |  |  styles.scss
          |  |  grid.scss
        gulpfile.js
        packages.json
    

    source is the folder where we will do our work. assets/style.css will be created by gulp when we process and combine our SASS files in source/scss. The bundle.js file will be created by gulp when we minify and combine all our JS files.

    A brief overview of gulp

    Gulp is a streaming build system. Its streaming nature is what allows it to pipe and pass around the data being manipulated or used by its plugins. The plugins are intended to only do one job each, so it’s not uncommon to pass a singular file through multiple plugins.

    The gulp API is incredibly light containing 4 top-level functions. They are

    • gulp.task
    • gulp.src
    • gulp.dest
    • gulp.watch

    gulp.task defines your tasks. Its arguments are name, deps and fn.

    Where name is a string, deps is an array of task names, and fn is the function that performs your task. Deps is optional so gulp.task in its two forms are:

        gulp.task('mytask', function() {
          //do stuff
        });
    
        gulp.task('dependenttask', ['mytask'], function() {
          //do stuff after 'mytask' is done.
        });
    

    gulp.src points to the files we want to use. Its parameters are globs and an optional options object. It uses .pipe for chaining its output into other plugins.

    gulp.dest points to the output folder we want to write files to.

    gulp.src and gulp.dest used to simply copy files looks like:

        gulp.task('copyHtml', function() {
          // copy any html files in source/ to public/
          gulp.src('source/*.html').pipe(gulp.dest('public'));
        });
    

    gulp.watch like gulp.task has two main forms. Both of which returns an EventEmitter that emits change events. The first of which takes a glob, an optional options object, and an array of tasks as its parameters.

        gulp.watch('source/javascript/**/*.js', ['jshint']);
    

    Simply put, when any of the files matched by the glob change, run the tasks. In the above code block, when any files in the source/javascript subfolders that have an extension of .js change, then the task jshint will be run against those files.

    The second form takes the glob, an optional options object, and an optional callback that will run when a change is picked up.

    You can compare this to grunt, which requires a secondary package to have the watch feature. Gulp has it built right in.

    For more information refer to the API docs.

    Tasks that are actually useful.

    Being able to tell us that it is running is a fine task, but let’s get gulp to do some real tasks for us.

    We’ll start with simple tasks and work our way up.

    JSHint on save

    Our first task will lint our JavaScript (check for errors) using jshint and we’ll also set it up to run this task each time we save a JavaScript file.

    To begin we’ll need the gulp-jshint package, grab it with npm. We’ll also need a reporter for jshint to make the output nicely formatted and color-coded; we’ll grab that too.

    1. npm install --save-dev gulp-jshint jshint-stylish

    Now we’ll add the lint task to our gulpfile.

    gulpfile.js
        // grab our packages
        var gulp   = require('gulp'),
            jshint = require('gulp-jshint');
    
        // define the default task and add the watch task to it
        gulp.task('default', ['watch']);
    
        // configure the jshint task
        gulp.task('jshint', function() {
          return gulp.src('source/javascript/**/*.js')
            .pipe(jshint())
            .pipe(jshint.reporter('jshint-stylish'));
        });
    
        // configure which files to watch and what tasks to use on file changes
        gulp.task('watch', function() {
          gulp.watch('source/javascript/**/*.js', ['jshint']);
        });
    

    So let’s step through what we’ve done.

    We’ve rewritten our default task to have the watch task as a dependency. What this means is that running

    1. gulp

    will run the watch task.

    Now let’s look at the new JSHint task. It sources any .js files that exist in source/javascript or any of its subdirectories. So a file at source/javascript/carousel/main.js would be picked up for the task just as well. These files are then passed into our gulp-jshint plugin, which then passes it into the stylish reporter to give us the JSHint results.

    We can run this task by doing:

    gulp jshint
    

    Super easy!

    Alright, now what about that watch task. It’s simple actually, if a change is detected in any of our JavaScript files, it runs the JSHint task.

    Sass Compilation with libsass

    Sass serves as a way to extend CSS giving support for variables, nested rules, mixins, inline imports, and more.

    Ken Wheeler has already done an awesome write-up on Sass that you can find here.

    For sass compilation, we’ll use gulp-sass

    Note: gulp-sass uses node-sass which in turn uses libsass. On windows you’ll need to install Python 2.7.x and Visual Studio Express 2013 in order to compile libsass. Mac and Linux will use whatever gcc is available.

    An alternative is to use gulp-ruby-sass, which uses ruby and the sass gem instead.

    gulpfile.js
        var gulp   = require('gulp'),
            jshint = require('gulp-jshint'),
            sass   = require('gulp-sass');
    
        /* jshint task would be here */
    
        gulp.task('build-css', function() {
          return gulp.src('source/scss/**/*.scss')
            .pipe(sass())
            .pipe(gulp.dest('public/assets/stylesheets'));
        });
    
        /* updated watch task to include sass */
    
        gulp.task('watch', function() {
          gulp.watch('source/javascript/**/*.js', ['jshint']);
          gulp.watch('source/scss/**/*.scss', ['build-css']);
        });
    

    We can also add sourcemaps using gulp-sourcemaps. If you’ve never used sourcemaps they’re an awesome feature that map processed, minified, or other modified files to their original sources.

    A list of the plugins that support gulp-sourcemaps can be found here.

    gulpfile.js
        var gulp       = require('gulp'),
            jshint     = require('gulp-jshint'),
            sass       = require('gulp-sass'),
            sourcemaps = require('gulp-sourcemaps');
    
        gulp.task('build-css', function() {
          return gulp.src('source/scss/**/*.scss')
            .pipe(sourcemaps.init())  // Process the original sources
              .pipe(sass())
            .pipe(sourcemaps.write()) // Add the map to modified source.
            .pipe(gulp.dest('public/assets/stylesheets'));
        });
    

    JavaScript concat and minify

    When working with a lot of JavaScript, you usually get to a point where you need to pull it all together. The general purpose plugin gulp-concat allows you to accomplish that easily.

    We can also go a step further and run it through uglify also to get a much smaller file size.

    Additionally, we’ll conditionally apply to uglify based on whether we’re building for production.

        gulp.task('build-js', function() {
          return gulp.src('source/javascript/**/*.js')
            .pipe(sourcemaps.init())
              .pipe(concat('bundle.js'))
              //only uglify if gulp is ran with '--type production'
              .pipe(gutil.env.type === 'production' ? uglify() : gutil.noop())
            .pipe(sourcemaps.write())
            .pipe(gulp.dest('public/assets/javascript'));
        });
    

    Summary

    We’ve only scratched the surface of gulp. Gulp can be as complex or as simple as you need it to be, and because it’s just code you can do just about anything you want as a task.

    From as simple as concating together JavaScript files, to automatically deploying to an S3 bucket on save. Gulp gives you the tools to do what you want quickly and easily.

    Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

    Learn more about us


    About the authors
    Default avatar
    Justin Rexroad

    author

    Still looking for an answer?

    Ask a questionSearch for more help

    Was this helpful?
     
    Leave a comment
    

    This textbox defaults to using Markdown to format your answer.

    You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

    Try DigitalOcean for free

    Click below to sign up and get $200 of credit to try our products over 60 days!

    Sign up

    Join the Tech Talk
    Success! Thank you! Please check your email for further details.

    Please complete your information!

    Get our biweekly newsletter

    Sign up for Infrastructure as a Newsletter.

    Hollie's Hub for Good

    Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

    Become a contributor

    Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

    Welcome to the developer cloud

    DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

    Learn more
    DigitalOcean Cloud Control Panel