Using gulp with grunt

Demonstration of how to use gulp inside of a grunt build process.

Skip the talk, where's the code?

Example code can be found at gulp-with-grunt.

Why

Grunt is the dominant build tool in the NodeJS community with a huge ecosystem of already built grunt plugins. Gulp provides a nice alternative in style as it prefers code over configuration. Gulp also enables extremely fast data transformations as it utilizes NodeJS streams. Technically I am demonstrating how to use NodeJS streams inside of Grunt tasks, but since most gulp plugins provide nice stream APIs for common tasks such as less, we will just call it gulp.

Example task

The below example task demonstrates how to use gulp inside a grunt task.

Note This could easily be adapted to use a grunt multi task's options and pass them into the gulp stream.

grunt.registerTask('styles', function () {

    // makes task async
    var done = this.async();

    grunt.log.writeln('grunt styles: start');

    gulp.
        src('src/styles.less').
        pipe(less()).
            on('error', function (err) {
                grunt.log.writeln('less() error event');
                grunt.fail.fatal(err.message);
            }).
            on('finish', function () {
                grunt.log.writeln('less() finish event');
            }).
        pipe(gulp.dest('dest')).
            on('error', function (err) {
                grunt.log.writeln('gulp.dest() error event');
                grunt.fail.fatal(err.message);
            }).
            // gulp.dest emits "close" event when stream is complete
            on('close', function () {
                grunt.log.writeln('gulp.dest() close event');
                grunt.log.writeln('grunt styles: finished');
                // Let grunt know async task is done.
                done();
            });
});

The trick is to utilize Grunt's async tasks with the events emitted from streams. Since this is a custom task you will need to utilize some of Grunt's API to make the task place nicely with others. Mainly this includes listening for stream's error events and calling grunt.fail.fatal(message) in conjunction with listening for the event used to signify the completion of the last stream. These "completion" events are typically finish for writable streams and close for readable streams as documented in the NodeJS stream doc.


Keith Loy

About Keith Loy

An expert in UI engineering specializing in mobile and web development. Deep understanding of javascript and vast experience utilizing javascript to build rich client experiences.


comments powered by Disqus