I have spent so many hours trying to find the perfect build process for my less/sass stylesheets and coffeescripts. There are several php packages for this but I’ve never been too happy with them and they often seem to fail for various and difficult to debug reasons.

Gulpjs is the answer to all your woes. It is a command-line tool that simply allows you to run build tasks.

Getting started with gulp

Follow these instructions to get gulp installed and running.

Plugins

There are numerous plugins available for gulp which provide all the functionality you could want.

You can install plugins through npm:

npm install gulp-concat gulp-coffee

Then require them at the top of your gulpfile.js:

var concat = require('gulp-concat');
var coffee = require('gulp-coffee');

Writing tasks

A good use case of gulp is compiling and combining coffeescripts in a single javascript file. So lets start with our first task:

gulp.task('coffeescripts', function() {
    return gulp.src('assets/scripts/**/*.coffee')
        .pipe(concat('combined.coffee'))
        .pipe(coffee())
        .pipe(gulp.dest('build/scripts/combined.js'));
});

This task finds all .coffee files in any folder within your scripts directory. These are combined into a single file then piped into a plugin that compiles coffeescripts into javascript and finally pushed into your build directory.

It is important to combine your coffeescripts before compiling them. This will ensure that all your classes are defined within a single (function() { ... })(); block and can easily reference each other without having to resort to the global window object.

You can run this task with gulp coffeescripts in your terminal.

Task dependancies

So now you’ve got your coffeescripts compiling, you may have some vendor javascripts that you want to also be built into the combined.js file. If you pipe these into your coffee() plugin you’ll get a bunch of errors. Instead it is best to have a separate task that only runs on .js files.

gulp.task('coffeescripts', function() {
    return gulp.src('assets/scripts/**/*.coffee')
        .pipe(concat('combined-coffee.coffee'))
        .pipe(coffee())
        .pipe(gulp.dest('assets/scripts/'));
});

gulp.task('scripts', ['coffeescripts'], function() {
    return gulp.src('assets/scripts/**/*.js')
        .pipe(concat('combined.js'))
        .pipe(uglify())
        .pipe(gulp.dest('build/scripts'));
});

By passing in ['coffeescripts'] to the scripts task you ensure it is run first. This compiles the coffeescripts into combined-coffee.js which is then combined with normal javascript files.

The uglify plugin minifies the scripts before they are piped into the build directory:

var uglify = require('gulp-uglify')

Running gulp scripts will now run the coffeescripts and scripts tasks.

Watchers and automated builds

Having to run the gulp command every time you make a change to a file is a bit of a faff, this can be automated for you using watchers.

gulp.task('watch', function() {
    gulp.watch([
        'assets/scripts/**/*.coffee',
        'assets/scripts/**/*.js'
    ], ['scripts']);

    gulp.watch([
        'assets/styles/**/*.sass',
        'assets/styles/**/*.css'
    ], ['styles']);
});

If any changes are made to one of the specified files, the related task will be run. You can start the watcher with:

gulp watch

Taking it further

There are lot of existing plugins for gulp and I’d suggest taking some time to look through and see which ones might prove useful in your code environment.

This example build script shows how I run my usual full build process, feel free it use it as you wish.

You may wish to install your dependancies through a package.json file and running npm install to ensure all your developers are working with the same node modules.