Skip to content

Gulp: browserify and ES6

Marco Solazzi edited this page Oct 28, 2015 · 5 revisions

This recipe will guide you through the installation and configuration of browserify and Babel (ES6) in the WOK workflow

Installation and Requirements

Install all dependencies

npm install browserify watchify babelify envify event-stream vinyl-buffer vinyl-source-stream --save-dev

Gulp tasks

Replace existing build/gulp-tasks/scripts.js contents with:

/**
 * JavaScript Related Task
 * ===============================
 */

module.exports = function (gulp, $, options) {

    var watchify = require('watchify'),
        browserify = require('browserify'),
        source = require('vinyl-source-stream'),
        buffer = require('vinyl-buffer'),
        _ = require('lodash'),
        es = require('event-stream'),
        glob = require('glob'),
        babelify = require('babelify'),
        envify = require('envify'),
        srcPath = options.assetsPath('src.js'),
        destPath = options.assetsPath('dist.js'),
        browserifyOptions;


    if (options.production) {
        destPath = destPath.replace(options.paths.dist.root, options.paths.tmp);
    }


    browserifyOptions = {
      debug: (!options.production)
    };

    function createBundle(entry) {

        var opts, b, browserSync;

        // add custom browserify options here
        opts = _.defaults({
            entries: [srcPath + '/' + entry]
        }, browserifyOptions);

        if (options.isWatching) {
            browserSync = require('browser-sync').get(options.buildHash);
        }

        function doBundle() {


            var bundle = b.bundle()
                .on('error', function (err) {
                    $.util.log($.util.colors.red('Browserify Error: ') + err);
                    this.emit('end');
                    if (!options.isWatching) {
                        process.exit(-1);
                    }
                })
                .pipe(source(entry))
                .pipe(buffer())
                .pipe($.sourcemaps.init({loadMaps: true})) // loads map from browserify file
                .pipe($.sourcemaps.write('./')) // writes .map file
                .pipe(gulp.dest(destPath));

            if (options.isWatching) {
                return bundle
                    .pipe($.if(options.livereload, browserSync.stream({match: '**/*.js'})))
                    .pipe($.notify({ message: 'JS Compiled', onLast: true }));
            }


            return bundle;
        }

        if (options.isWatching) {
            b = watchify(browserify( _.assign(opts, watchify.args) ));


            b.on('update', doBundle);

            b.on('log', function (msg) {
                $.util.log($.util.colors.green('Bundle ' + entry + ': ' + msg.toString()));
            });

        } else {
            b = browserify(opts);
            b.on('bundle', function () {
                $.util.log($.util.colors.green('Bundle ' + entry + ' created'));
            });
        }

        b.transform(envify, {
            NODE_ENV: options.production ? 'production' : 'development'
        });

        b.require('babelify/polyfill');
        b.transform(babelify.configure({
            optional: ['strict'],
            loose: [
                'es6.arrowFunctions',
                'es6.blockScoping',
                'es6.classes',
                'es6.constants',
                'es6.forOf',
                'es6.modules',
                'es6.parameters',
                'es6.properties.computed',
                'es6.properties.shorthand',
                'es6.tailCall',
                'es6.templateLiterals',
                'es6.regex.unicode',
                'es6.regex.sticky'
            ]
        }));


        return doBundle();

    }



    gulp.task('scripts', function (done) {

        var files = glob.sync('*.js', {
            ignore: '*.{spec,conf}.js',
            cwd: srcPath
        });

        if (files.length === 0) {
            done();
        }

        return es.merge(files.map(createBundle));


    });

    gulp.task('scripts:watch', function (done) {

        var files = glob.sync('*.js', {
            ignore: '*.{spec,conf}.js',
            cwd: srcPath
        });

        if (files.length === 0) {
            done();
        }

        return es.merge(files.map(createBundle));

    });

};

This will register two tasks:

  • gulp scripts: one time script compilation
  • gulp scripts:watch: launch browserify in watch mode and live-reload browser on change

Workflow integration

Open build/gulp-tasks/serve.js and replace these lines:

gulp.watch([
    assetsPath('src.js') + '/**/*.js',
    '!' + assetsPath('src.js') + '/**/*.{spec,conf}.js'
], ['scripts-watch']);

with these line:

gulp.run('scripts:watch');

Linting

To enable ES6 linting in eslint follow this recipe

Caveats

  • Script minification is still demanded to the view task for better integration with existing scripts.