Gulp 4, Babel & Browserify

This post is referring to Gulp 4, Babel 7.8, Babel 6 and browserify 16.

  • Babel - use or write latest javascript today and still have browser compatibility
  • Browserify - use nodejs require in browser and bundle it all into one file

The gulp flow is transform each file (with babel) into javascript that most browser understand, then bundle it all into (using browserify) into one file and minify it before saving it into our dist folder.

I put two version of this because one is to simply use the latest npm modules and this could be buggy and something might not work. The other one is the latest stable version which the one you should probably get.

I wasted hours for this and hope you don't have to.

Steps (for beginner):

  1. Install the desired npm modules
  2. Create a file called gulpfile.js in your project root
  3. Run Gulp:

    • gulp installed as global and local

      run gulp in your terminal or command line in your project folder

    • gulp installed as project dev dependency only

      add to "build" script in your package.json as below and run npm run build

"script": {
  "build": "gulp"
}

Stable and more browser support with Babel 6

  • Note that with babel 6 we have a different set of babel modules
npm install -D gulp babelify@8 babel-core babel-preset-env gulp-sourcemaps gulp-terser-js browserify vinyl-buffer vinyl-source-stream babel-plugin-transform-runtime

npm install babel-runtime
// babel 6 + babelify 8 - stable
const { dest, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const terser = require('gulp-terser-js');
const browserify = require('browserify');
const source  = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

const files = {
  jsMain: './src/app.js',
  jsOutput: 'app.bundle.js'
}

function jsTask() {
  return browserify(files.jsMain, {debug:true})
    .transform('babelify', {
      presets: ['babel-preset-env'],
      plugins: ['babel-plugin-transform-runtime']
    })
    .bundle()
    .pipe(source(files.jsOutput))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(terser())
    .pipe(sourcemaps.write('.'))
    .pipe(dest("dist"));
};

exports.default = series(parallel(jsTask));

I want browserify, watchify and tinyify altogether

Well then, let's add 2 more additional modules:

npm i -D watchify tinyify
  • note your babel version, presets and plugin
const { dest, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
// const terser = require('gulp-terser-js'); // we don't need terser
const browserify = require('browserify');
const source  = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const watchify = require('watchify'); // they say it caching bundler for browserify

const files = {
  jsMain: './src/app.js',
  jsOutput: 'app.bundle.js'
}

function jsTask() {
  return watchify(browserify(files.jsMain, {debug:true})
    .transform('babelify', {
      presets: ['babel-preset-env'],
      plugins: ['babel-plugin-transform-runtime']
    }).plugin('tinyify'))
    .bundle()
    .pipe(source(files.jsOutput))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(sourcemaps.write('.'))
    .pipe(dest("dist"));
};

exports.default = series(parallel(jsTask));

Bonus: Watch changes and auto browserify

  • note your babel version, presets and plugin
const { watch, dest, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const browserify = require('browserify');
const source  = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const watchify = require('watchify');

const files = {
  jsPath: 'src/**/*.js',
  jsMain: './src/app.js',
  jsOutput: 'app.bundle.js'
}

function jsTask() {
  return watchify(browserify(files.jsMain, {debug:true})
    .transform('babelify', {
      presets: ['babel-preset-env'],
      plugins: ['babel-plugin-transform-runtime']
    }).plugin('tinyify'))
    .bundle()
    .pipe(source(files.jsOutput))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(sourcemaps.write('.'))
    .pipe(dest("dist"));
};

function watchTask() {
  watch([files.jsPath],
    parallel(jsTask))
}

exports.default = series(parallel(jsTask), watchTask);

I live in the cutting edge NPM Modules

npm install -D gulp babelify @babel/core @babel/preset-env gulp-sourcemaps gulp-terser-js browserify vinyl-buffer vinyl-source-stream @babel/plugin-transform-runtime

npm install @babel/runtime # require for babel runtime
  • gulp-sourcemaps are optional
  • declare browserlist in package.json
  • These are example of working gulpfile (at time of writing) and i tested it before post it here.
// babel 7 + babelify 10 - Cutting Edge
const { dest, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const terser = require('gulp-terser-js');
const browserify = require('browserify');
const source  = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

const files = {
  jsMain: './src/app.js',
  jsOutput: 'app.bundle.js'
}

function jsTask() {
  return browserify(files.jsMain, {debug:true})
  .transform('babelify', {
      presets: ['@babel/env'],
      plugins: ['@babel/transform-runtime']
    })
    .bundle()
    .pipe(source(files.jsOutput))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(terser())
    .pipe(sourcemaps.write('.'))
    .pipe(dest("dist"));
};

exports.default = series(parallel(jsTask));

References

  1. https://www.npmjs.com/package/gulp-babel
  2. https://github.com/babel/babelify
  3. https://babeljs.io/docs/en/6.26.3/babel-plugin-transform-runtime
  4. https://github.com/browserify/browserify