on Writings, Blog, JavaScript, grunt, gulp, Code

Why choose Gulp over Grunt - what to look for in a build tool

Grunt and Gulp are both build tools used to automate your workflow, but which one is better? We can judge this by thinking about what we want from a build tool. To be most effective, a build tool must be:

  • Fast (e.g. fast live editing)
  • Community-driven (add plugins, popular on stackoverflow)
  • Modular & Extensible
  • Feature-rich
  • Solve problems out the box

Both Grunt and Gulp cover most of the above, but Gulp has 2 significant advantages over grunt:

  • Gulp is built for speed and can execute tasks in parallel
  • Gulp can convert open files into super fast streams internally.

grunt-vs-gulp

Code over configuration, or configuration over code?

The 2 advantages of Gulp come from the way it's been built to focus on code over configuration. You can also just use normal JavaScript, and easily extend or modify tasks that don’t work for you. Conversely, Grunt focuses on configuration - but what does that mean in practice?

Gruntfile.js

To explain, let's compare grunt and gulp config files. First, look at the grunt configuration file (gruntfile) below:

  grunt.initConfig({
    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
      options: {
        globals: {
          jQuery: true
        }
      }
    },
    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');

  grunt.registerTask('default', ['jshint']);

};

It's basically a JavaScript config object that configures certain tasks, such as concat and uglify. To change any of these tasks, you have to go into the actual plugin themselves.

Gulpfile.js

Now compare grunt's config file to gulp's version below:

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

gulp.task('default', function() {  
  // use gulp watch to listen for changes in sass, then execute styles task
  gulp.watch('sass/**/*.scss', ['styles']);
});

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

  gulp.src('sass/**/*.scss')
      //pipe sass to convert scss to css
      .pipe(sass()
          //on sass error, don't break the build, just log an error
          .on('error', sass.logError))
      //pipe autoprefixer
      .pipe(autoprefixer({
          browsers:['last 2 versions']
      }))
      //save css to css folder
      .pipe(gulp.dest('./css'))

})

As you can see, the gulpfile is much more like standard javascript, and at any given point you can intervene and pipe your files into another function before moving on.

Why is Gulp faster than Grunt?

Speed is important in a build tool, and one reason why Grunt is slower is because it executes tasks in sequence, one after another. Gulp on the other hand, executes tasks in parallel by default, and finishes when all have finished.

That’s not only what makes Gulp faster.
Gulp also comes with a concept called streams, which cost much less I/O and file system access.

How streams make Gulp faster

Grunt has tasks which copy your files to a temporary place where changes are made to them, resulting in every task incurring a penalty for I/O and file system operations:

Gulp flow

Gulp on the other hand, converts your input file into an in memory stream - so the I/O is only done at the beginning and very end of all the tasks.

Gulp streams

So much faster!