How To: Basic Tasks in Gulp.js

If you’re familiar with GruntJS, you might be familiar with Gulp.js. Both are very similar, Gulp is the newer kid on the block that requires significantly less configuration to write tasks.

If you’re new to Gulp or perhaps already use it, but not sure how to do specific tasks with it, see below for a list of basic tasks you can achieve in Gulp.js.

There is a complete gulpfile.js at the bottom of this page containing all include files as well as directives if you struggle to follow along.

Error Handling using Plumber

Plumber is a plugin for Gulp that allows you to capture errors and not break the Gulp process when something goes wrong. All examples below will assume “gulp-plumber” is defined in your package.json file and installed.

At the top of your gulpfile.js, you will want to define the error handler all tasks will be using for Plumber.

var onError = function(err) {
    console.log(err);
}

Copying Files

Sometimes you might want to move files from one location to another. This example allows you to glob files from a source directory and all sub-directories within it.

Change the file extensions below to your desired extensions, or to copy everything in a folder and subfolders, replace the curly braces with a * so you have . which will grab everything and copy to the destination folder.

gulp.task('copyfiles', function() {
    gulp.src('./source_directory/**/*.{ttf,woff,eof,svg}')
    .pipe(gulp.dest('./destination_directory'));
});

Compress Images

Reduce the file size of your projects images by compressing them using this helpful task.

gulp.task('images', function() {
    var imgSrc = './src/images/**/*',
        imgDst = './images';

    return gulp.src(imgSrc)
        .pipe(plumber({
            errorHandler: onError
        }))
        .pipe(changed(imgDst))
        .pipe(imagemin())
        .pipe(gulp.dest(imgDst))
        .pipe(notify({ message: 'Images task complete' }));
});

Compiling Sass/Compass

If you’re using Sass as your pre-processor of choice, then you’ll want to know how to compile your styles using Gulp.

Required plugins

  • gulp-compass
  • gulp-notify
gulp.task('styles', function() {
    return gulp.src('./src/sass/*.scss')
        .pipe(plumber({
            errorHandler: onError
        }))
        .pipe(compass({
            config_file: './config.rb',
            css: './css',
            sass: './sass'
        }))
        .pipe(gulp.dest('./css'))
        .pipe(notify({ message: 'Styles task complete' }));
});

Hinting Your Javascript

Ensure your Javascript conforms to appropriate coding guidelines, no missing semicolons, no repeated variables or scope issues. This is a must have in your workflow. To control how strict the hinter is, change the default value to any valid value.

Required plugins

  • gulp-jshint
  • gulp-notify
gulp.task('jshint', function() {
    return gulp.src('./src/scripts/*.js')
    .pipe(plumber({
        errorHandler: onError
    }))
    .pipe(jshint())
    .pipe(jshint.reporter('default'))
    .pipe(notify({ message: 'JS Hinting task complete' }));
});

Combine/Minify Your Javascript

Required plugins

  • gulp-concat
  • gulp-strip-debug
  • gulp-uglify
  • gulp-notify
gulp.task('scripts', function() {
    return gulp.src('./src/scripts/*.js')
        .pipe(plumber({
            errorHandler: onError
        }))
        .pipe(concat('app.min.js'))
        .pipe(stripDebug())
        .pipe(uglify())
        .pipe(gulp.dest('./js/'))
        .pipe(notify({ message: 'Scripts task complete' }));
});

Watching / Reloading For Live Changes

Having to keep calling “gulp” isn’t any fun, using gulp-livereload, we can spin up a liveReload server instance to watch our files and run certain tasks again (thus automating our front-end workflow). Take note of other tasks being called inside of this watch block, this is where our liveReload server action happens.

Required plugins

  • gulp-live-reload
  • gulp-notify
gulp.task('watch', function() {
    // Check for modifications in particular directories

    // Whenever a stylesheet is changed, recompile
    gulp.watch('./src/sass/**/*.scss', ['styles']);

    // If user-developed Javascript is modified, re-run our hinter and scripts tasks
    gulp.watch('./src/scripts/**/*.js', ['jshint', 'scripts']);

    // If an image is modified, run our images task to compress images
    gulp.watch('./src/images/**/*', ['images']);

    // Create a LiveReload server
    var server = liveReload();

    // Watch any file for a change in the 'src' folder and reload as required
    gulp.watch(['./src/**']).on('change', function(file) {
        server.changed(file.path);
    })
});

Final gulpfile.js

See below for a fully functional gulpfile.js complete with all of the required modules for running tasks.

var gulp       = require('gulp'),
	changed    = require('gulp-changes'),
	compass    = require('gulp-compass'),
	concat     = require('gulp-concat'),
	imagemin   = require('gulp-imagemin'),
	jshint     = require('gulp-jshint'),
	notify     = require('gulp-notify'),
	plumber    = require('gulp-plumber'),
	stripDebug = require('gulp-strip-debug'),
	uglify     = require('gulp-uglify'),
	liveReload = require('gulp-live-reload');

// Gulp plumber error handler
var onError = function(err) {
	console.log(err);
}

// Lets us type "gulp" on the command line and run all of our tasks
gulp.task('default', ['copyfiles', 'images', 'jshint', 'scripts', 'styles', 'watch']);

// Copy fonts from a module outside of our project (like Bower)
gulp.task('copyfiles', function() {
	gulp.src('./source_directory/**/*.{ttf,woff,eof,svg}')
	.pipe(gulp.dest('./fonts'));
});

// Compress and minify images to reduce their file size
gulp.task('images', function() {
	var imgSrc = './src/images/**/*',
		imgDst = './images';

	return gulp.src(imgSrc)
		.pipe(plumber({
			errorHandler: onError
		}))
		.pipe(changed(imgDst))
		.pipe(imagemin())
		.pipe(gulp.dest(imgDst))
		.pipe(notify({ message: 'Images task complete' }));
});

// Hint all of our custom developed Javascript to make sure things are clean
gulp.task('jshint', function() {
	return gulp.src('./src/scripts/*.js')
	.pipe(plumber({
		errorHandler: onError
	}))
	.pipe(jshint())
	.pipe(jshint.reporter('default'))
	.pipe(notify({ message: 'JS Hinting task complete' }));
});

// Combine/Minify/Clean Javascript files
gulp.task('scripts', function() {
	return gulp.src('./src/scripts/*.js')
		.pipe(plumber({
			errorHandler: onError
		}))
		.pipe(concat('app.min.js'))
		.pipe(stripDebug())
		.pipe(uglify())
		.pipe(gulp.dest('./js/'))
		.pipe(notify({ message: 'Scripts task complete' }));
});

// Combine and minify Sass/Compass stylesheets
gulp.task('styles', function() {
	return gulp.src('./src/sass/*.scss')
		.pipe(plumber({
			errorHandler: onError
		}))
		.pipe(compass({
			config_file: './config.rb',
			css: './css',
			sass: './sass'
		}))
		.pipe(gulp.dest('./css'))
		.pipe(notify({ message: 'Styles task complete' }));
});

// This handles watching and running tasks as well as telling our LiveReload server to refresh things
gulp.task('watch', function() {
	// Check for modifications in particular directories

	// Whenever a stylesheet is changed, recompile
	gulp.watch('./src/sass/**/*.scss', ['styles']);

	// If user-developed Javascript is modified, re-run our hinter and scripts tasks
	gulp.watch('./src/scripts/**/*.js', ['jshint', 'scripts']);

	// If an image is modified, run our images task to compress images
	gulp.watch('./src/images/**/*', ['images']);

	// Create a LiveReload server
	var server = liveReload();

	// Watch any file for a change in the 'src' folder and reload as required
	gulp.watch(['./src/**']).on('change', function(file) {
		server.changed(file.path);
	})
});