32
votes

I'm trying to write a gulp task allowing me to use modules in JS (CommonJS is fine), using browserify + 6to5. I also want source mapping to work.

So: 1. I write modules using ES6 syntax. 2. 6to5 transpiles these modules into CommonJS (or other) syntax. 3. Browserify bundles the modules. 4. Source maps refers back to the original ES6 files.

How to write such a task?

Edit: Here's what I have so far:

gulp task

gulp.task('browserify', function() {
    var source = require('vinyl-source-stream');
    var browserify = require('browserify');
    var to5ify = require('6to5ify');

    browserify({
        debug: true
    })
    .transform(to5ify)
    .require('./app/webroot/js/modules/main.js', {
        entry: true
    })
    .bundle()
    .on('error', function(err) {
        console.log('Error: ' + err.message);
    })
    .pipe(source('bundle.js'))
    .pipe(gulp.dest(destJs));
});

modules/A.js

function foo() {
    console.log('Hello World');

    let x = 10;

    console.log('x is', x);
}

export {
    foo
};

modules/B.js

import {
    foo
}
from './A';

function bar() {
    foo();
}

export {
    bar
};

modules/main.js

import {
    bar
}
from './B';

bar();

The code seems to be working, but it's not minified and the source map is inline (which is not really working for production).

2

2 Answers

46
votes

Use this as your start point:

var gulp = require('gulp');
var gutil = require('gulp-util');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var to5ify = require('6to5ify');
var uglify = require('gulp-uglify');

gulp.task('default', function() {
  browserify('./src/index.js', { debug: true })
    .transform(to5ify)
    .bundle()
    .on('error', gutil.log.bind(gutil, 'Browserify Error'))
    .pipe(source('bundle.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true})) // loads map from browserify file
    .pipe(uglify())
    .pipe(sourcemaps.write('./')) // writes .map file
    .pipe(gulp.dest('./build'));
});
3
votes

I didn't understand why we had to use certain things in order to get this to work so I'm adding my own answer here. For those looking for a solution with babelify, I added one below. I also thought it'd be good to talk about what each line does.

For those that want to use ES6 in their Gulpfile, you can look here but Gulp supports it if you rename your file to Gulpfile.babel.js as of Gulp 3.9

One big thing to note is you need to use vinyl-source-stream with Browserify in order to convert the output into something Gulp can understand. From there a lot of gulp plugins require vinyl buffers which is why we buffer the source stream.

For those not familiar with sourcemaps, they are essentially a way for you to map your minifed bundled file to the main source file. Chrome and Firefox support it so when you debug you can look at your ES6 code and where it failed.

import gulp          from 'gulp';
import uglify        from 'gulp-uglify';
import sourcemaps    from 'gulp-sourcemaps';
import source        from 'vinyl-source-stream';
import buffer        from 'vinyl-buffer';
import browserify    from 'browserify';
import babel         from 'babelify';

gulp.task('scripts', () => {
  let bundler = browserify({
    entries: ['./js/main.es6.js'], // main js file and files you wish to bundle
    debug: true,
    extensions: [' ', 'js', 'jsx']
  }).transform(babel.configure({
    presets: ["es2015"] //sets the preset to transpile to es2015 (you can also just define a .babelrc instead)
  }));

  // bundler is simply browserify with all presets set
  bundler.bundle()
    .on('error', function(err) { console.error(err); this.emit('end'); })
    .pipe(source('main.es6.js')) // main source file
    .pipe(buffer())
    .pipe(sourcemaps.init({ loadMaps: true })) // create sourcemap before running edit commands so we know which file to reference
      .pipe(uglify()) //minify file
      .pipe(rename("main-min.js")) // rename file
    .pipe(sourcemaps.write('./', {sourceRoot: './js'})) // sourcemap gets written and references wherever sourceRoot is specified to be
    .pipe(gulp.dest('./build/js'));
});

Other useful readings:

Gulp browserify the gulp-y way