Last Updated: February 25, 2016
· optilude

Gulpfile for projects with LESS, Browserify and React

This gulpfile.js provides the following:

  • A js target that builds a JavaScript bundle using browserify
  • A css target that builds a single CSS file using less
  • Support for a --production flag, which will minify sources
  • A watch target that runs watchify for the JavaScript sources and standard for the LESS sources for robust real-time reloading of both.

Configure it by changing the variables near the top, under the imports.

You need to install a bunch of packages:

$ npm install --save-dev browserify reactify watchify vinyl-source-stream gulp gulp-sourcemaps gulp-util vinyl-buffer gulp-less yargs gulp-if gulp-minify-css gulp-uglify

Then create gulpfile.js as per below:

/*jshint globalstrict:true, devel:true, newcap:false */
/*global require */

 * Build CSS and JavaScript using `gulp`.
 * Main targets are: `js`, `css` and `watch`.
 * Run with `--production` to get minified sources.

"use strict";

var argv = require('yargs').argv,

    gulp       = require('gulp'),
    gutil      = require('gulp-util'),
    gulpif     = require('gulp-if'),

    source     = require('vinyl-source-stream'),
    buffer     = require('vinyl-buffer'),
    sourcemaps = require('gulp-sourcemaps'),
    browserify = require('browserify'),
    watchify   = require('watchify'),
    reactify   = require('reactify'),
    uglify     = require('gulp-uglify'),

    less       = require('gulp-less'),
    minifyCSS  = require('gulp-minify-css');

// Directory where static files are found. Don't forget the slash at the end.
var staticDirectory = './static/',

    // Source and target JS files for Browserify
    jsMainFile      = staticDirectory + 'js/app.jsx',
    jsBundleFile    = 'bundle.js',

    // Source and target LESS files
    cssMainFile     = staticDirectory + 'less/styles.less',
    cssFiles        = staticDirectory + 'less/**/*.less';

// Browserify bundler, configured for reactify with sources having a .jsx extension
var bundler = browserify({
    entries: [jsMainFile],
    transform: [reactify],
    extensions: ['.jsx'],
    debug: !argv.production,
    cache: {}, packageCache: {}, fullPaths: true // for watchify

// Build JavaScript using Browserify
gulp.task('js', function() {
    return bundler
        .pipe(gulpif(!argv.production, sourcemaps.init({loadMaps: true}))) // loads map from browserify file
        .pipe(gulpif(!argv.production, sourcemaps.write('./'))) // writes .map file
        .pipe(gulpif(argv.production, uglify()))

// Build CSS
gulp.task('css', function(){
    return gulp.src(cssMainFile)
        .pipe(gulpif(argv.production, minifyCSS({keepBreaks:true})))

// Watch JS + CSS using watchify +

gulp.task('watchify', function() {
    var watcher  = watchify(bundler);
    return watcher
    .on('error', gutil.log.bind(gutil, 'Browserify Error'))
    .on('update', function () {
        .pipe(sourcemaps.init({loadMaps: true})) // loads map from browserify file
        .pipe(sourcemaps.write('./')) // writes .map file

        gutil.log("Updated JavaScript sources");
    .bundle() // Create the initial bundle when starting the task

gulp.task('csswatch', function () {, ['css']);

gulp.task('watch', ['watchify', 'csswatch']);
gulp.task('default', ['js', 'css']);