Gulp.js : A Better Alternative to Grunt.js

Recently, we have started a single page application (SPA) demo in github with AngularJS. When we start this project, my plan was to use Grunt.js for task automation. But later, I have observed that there is a new framework named Gulp.js, that provides more cleaner and elegant syntax, which is easy to read and easy to write comparing to Grunt.js. Then I have evaluated the framework and really impressed with Gulp.js. Now I highly recommend Gulp.js over Grunt.js mainly due to its cleaner syntax.

Getting Started with Gulp.js

Like Grunt.js, Gulp.js is also provides as a NPM module so that you can install it through NPM. In order to working Gulp.js, you need to install Gulp globally and locally for your project.

The command below install gulp globally on your machine.

npm install –g gulp

You also need to install gulp locally for your project. If you haven’t a package.json file for your project, just create it.

The command below install gulp locally and will automatically add dependency into the devDependencies of package.json.

npm install --save-dev gulp

Now we have installed Gulp.js. The next step is to add a Gulp file named “gulpfile.js” for automating our tasks for the project. Let’s add a gulpfile.js file. The code block below shows a basic gulpfile.js file where we are just specifying a task named “build” by using the Node.js module gulp.

var gulp = require('gulp');
 
gulp.task('build', function () {
});

Automating Tasks with Gulp.js

There are lot of useful plugins are available for Gulp.js, which can be used for building most of the commonly used task automations. When I write this post, there are 310 gulp plugins available for automating your tasks. All plugins can install by using npm.

Minifying JavaScript Code

Let’s automate our tasks in the AngularJS SPA reference app webapi-angularjs-spa. Let’s start our automation tasks with minifying our JavaScript code files. For this task, we are using the following gulp plugins:

  • gulp-uglify
  • gulp-concat
  • gulp-size

The above plugins are using for minifying, concatenating minified files and getting size of the minified file respectively.

Let’s install these npm modules.

npm install --save-dev gulp-uglify gulp-concat gulp-size

The code block below shows a task named “app-js-minify” which minifies all JavaScript files written in AngularJS.

var filePath = {
    appjsminify: { src: './app/**/*.js', dest: './app' },
    libsjsminify: { src: ['libs/**/*.js',
 '!*.min.js', '!/**/*.min.js'], dest: 'libs/' },
    jshint: { src: './app/**/*.js' },
    minifycss: { src: ['../Content/themes/**/*.css',
 '!*.min.css', '!/**/*.min.css'],
  dest: '../Content/themes/' }
};
 
 
gulp.task('app-js-minify', function () {
    gulp.src(filePath.appjsminify.src)
        .pipe(uglify())
        .pipe(concat('ngscripts.js'))
        .pipe(size())
        .pipe(gulp.dest(filePath.appjsminify.dest));
});

In the above code block, we are specifying the code files to be minified by using the src method of gulp. We use gulp’s method .pipe() to pipe the source files into a gulp plugin. The concat function bundles all minified files to a file named “ngscripts.js” into a destination folder that specified using the function dest. The size returns the size of the minified file “ngscripts.js”. We have specified all files paths in a variable filepath. By default, tasks in Gulp.js, will be executed asynchronously.

Let’s run our first task “app-js-minify” by run the command “gulp app-js-minify” as shown in below figure.

image

Automating Unit Tests with Mocha

Let’s automate our unit tests with Gulp. We use the gulp plugin “gulp-mocha" for automating unit tests with Mocha.

gulp.task('mocha', function () {
    gulp.src('./test/*.js')
        .pipe(mocha({ reporter: 'list' }));
});

Minifying CSS

We use gulp plugingulp-minify-css” for minifying CSS files. In this task we also use a gulp plugin “gulp-rename” for rename the file.

gulp.task('minify-css', function () {    
    gulp.src(filePath.minifycss.src)
    .pipe(minifycss())
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest(filePath.minifycss.dest));
});

The below gulpfile is taken from our AngularJS SPA demo app.

var gulp = require('gulp'),
    gutil = require('gulp-util'),
    uglify = require('gulp-uglify'),
    jshint = require('gulp-jshint'),
    concat = require('gulp-concat'),
    jshintreporter = require('jshint-stylish'),
    minifycss = require('gulp-minify-css'),
    size = require('gulp-size'),
    clean = require('gulp-clean'),
    rename = require('gulp-rename');
 
var filePath = {
    appjsminify: { src: './app/**/*.js',
 dest: './app' },
    libsjsminify: { src: ['libs/**/*.js', '!*.min.js',
 '!/**/*.min.js'], dest: 'libs/' },
    jshint: { src: './app/**/*.js' },
    minifycss: { src: ['../Content/themes
    /**/*.css',
 '!*.min.css', '!/**/*.min.css'], 
dest: '../Content/themes/' }
};
 
 
gulp.task('app-js-minify', function () {
    gulp.src(filePath.appjsminify.src)
        .pipe(uglify())
        .pipe(concat('ngscripts.js'))
        .pipe(size())
        .pipe(gulp.dest(filePath.appjsminify.dest));
});
 
gulp.task('libs-js-minify', function () {
    /*Excludes already minified files.*/
    gulp.src(filePath.libsjsminify.src)
    .pipe(uglify())
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest(filePath.libsjsminify.dest));
});
 
 
gulp.task('jshint', function () {
    gulp.src(filePath.jshint.src)
      .pipe(jshint())
      .pipe(jshint.reporter(jshintreporter));
});
 
 
gulp.task('minify-css', function () {
    /*Excludes already minified files.*/
    gulp.src(filePath.minifycss.src)
    .pipe(minifycss())
    .pipe(rename({ suffix: '.min' }))
    .pipe(gulp.dest(filePath.minifycss.dest));
});
 
gulp.task('clean', function () {
    gulp.src(
        [
            'app/ngscripts.js',
            'libs/angular-ui/select2.min.js',
            'libs/select2/select2.min.js',
            'libs/semantic/semantic.min.js',
            'libs/jquery-1.9.1.min.js',
            '../Content/themes/semantic/
              semantic.min.css',
            '../Content/themes/Site.min.css',
            '../Content/themes/select2/
            select2.min.css'
        ], { read: false })
    .pipe(clean({force:true}));
});
gulp.task('build', ['app-js-minify', 'libs-js-minify', 'minify-css']);
gulp.task('cleanbuild', ['clean']);

You can run the gulp task by specifying the task name. In the above gulpfile, we are specifying two tasks at the end of the section named “build” and “cleanbuild” where we are specifying logically related group of tasks. You can pass these tasks as an array of defined tasks.

gulp.task('build', ['app-js-minify', 'libs-js-minify',
 'minify-css']);
gulp.task('cleanbuild', ['clean']);

When we run “gulp build” it will run tasks “app-js-minify”, “libs-js-minify” and “minify-css”. When we run “gulp cleanbuild” it will run the task “clean”. If you are simply running gulp without specifying any task, it will look for the task with name “default”.

The code block below provides the package.json file of the project

{
  "name": "webapi-angularjs-spa",
  "description": "SPA Demo app with AngularJS",
  "author": "Shiju Varghese",
  "version": "0.5.0",
  "repository": 
      "https://github.com/MarlabsInc/webapi-angularjs-spa",
  "dependencies": {},
  "devDependencies": {
    "gulp-util": "~2.2.14",
    "gulp": "~3.5.2",
    "gulp-concat": "~2.1.7",
    "gulp-uglify": "~0.2.1",
    "jshint": "~2.4.3",
    "gulp-jshint": "~1.4.2",
    "jshint-stylish": "~0.1.5",
    "gulp-minify-css": "~0.3.0",
    "gulp-rename": "~1.1.0",
    "gulp-size": "~0.1.3",
    "gulp-clean": "~0.2.4"
  }
}

Source Code

We have implemented the task automation in our AngularJS demo app which is available on github at https://github.com/MarlabsInc/webapi-angularjs-spa. The JavaScript client app is available from the location here. The gulpfile is available from here.

You can follow me on Twitter @shijucv

 

No Comments