Compile and Bundle Javascript es6 with Browserify + Babelify + Gulp
Tags: gulp, javascript, beginners, html
Published: 2021-03-05 15:37:06

My story began while I was trying to use the `tiny slider` npm package in my project and I used Gulp as my task runner.

I got an error when I tried to import the `tiny slider` js file in the script file of my project.

```
// my gulp file
const { src, dest } = require('gulp');
// minify JS
const uglify = require('gulp-uglify');
// support JS for old browsers
const babel = require('gulp-babel');
// create source map files to JS
const sourcemaps = require('gulp-sourcemaps');
// rename files
const rename = require('gulp-rename');
const replace = require('gulp-replace');

const srcFiles = {
  jsPath: 'src/js/**/*.js'
};

const distFiles = {
  distJSPath: 'dist/js',
};

// my js task
function jsTask() {
  return (
    src([srcFiles.jsPath])
      // To load existing source maps
      // This will cause sourceMaps to use the previous sourcemap to create an ultimate sourcemap
      .pipe(gulpif(!production, sourcemaps.init({ loadMaps: true })))
      .pipe(
        gulpif(
          production,
          babel({
            presets: ['@babel/preset-env'],
          })
        )
      )
      .pipe(concat('all.js'))
      .pipe(gulpif(production, rename({ extname: '.min.js' })))
      .pipe(gulpif(production, uglify()))
      .pipe(gulpif(!production, sourcemaps.write('./')))
      .pipe(dest(distFiles.distJSPath))
  );
}
```

```
// my script file
import { tns } from '../../node_modules/tiny-slider/src/tiny-slider';

```

I got these errors:

`Uncaught SyntaxError: Cannot use import statement outside a module`

`GET http://localhost:3000/node_modules/tiny-slider/src/tiny-slider net::ERR_ABORTED 404 (Not Found)`

Let's start to explain what is the problem then we learn to solve it.

I used `gulp-babel` to compile ES6 to ES5. The problem is that `require` is not defined in the browser and in the ES5 syntax. So we need to search for another method to bundle all required js modules into one file.

We need this `Browserify + Babelify` combination to Compile & Bundle.

- `Browserify` bundles js modules into one file to be used in the browser.

- 'gulp-babel' didn't match with `Browserify` so, we will use `Babelify` instead to convert ES6 to ES5.


Steps are as the following:

```
npm i --save-dev browserify

npm i --save-dev  babelify

// has all packages needed for babelify to work
npm i --save-dev @babel/core

// to tap the specific preset to compile our script
npm i --save-dev @babel/preset-env


// grab source after bundling of browserify and check if entry source is still piped.
npm i --save-dev vinyl-source-stream

// to continue with using source map and uglify
npm i --save-dev vinyl-buffer

```

In `package.json`, We need to specify the `preset`.

```
"devDependencies": {
    "@babel/core": "^7.13.8",
    "@babel/preset-env": "^7.9.6",
    "babel-core": "^6.26.3",
    "babel-preset-env": "^1.7.0",
    "babelify": "^8.0.0",
    "browser-sync": "^2.26.7",
    "browserify": "^17.0.0",
    .......
  },
  "babel": {
    "presets": [
      "@babel/preset-env"
    ]
  }
```
In gulp file:

We can run js task for each group of files separately ex: a script for front-end and script for back-end.

```
// define entry for browserify
const jsSrc = 'module.js';
const jsFolder = 'src/js/';

// we can add a script for front-end and script for back-end and so on
const jsFiles = [jsSrc];
```

```
const srcFiles = {
  jsPath: 'src/js/**/*.js',
  jsFiles: 'src/js/',
}
```

```
const browserify = require('browserify');
const babelify = require('babelify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');

async function jsTask() {
  jsFiles.map(function (entry) {
    return (
      browserify({
        entries: [jsFolder + entry],
      })
        .transform(babelify, { presets: ['@babel/preset-env'] })
        .bundle()
        .pipe(source('all.js'))
        // To load existing source maps
        // This will cause sourceMaps to use the previous sourcemap to create an ultimate sourcemap
        .pipe(gulpif(production, rename({ extname: '.min.js' })))
        .pipe(buffer())
        .pipe(gulpif(!production, sourcemaps.init({ loadMaps: true })))
        // .pipe(concat('all.js'))
        .pipe(gulpif(production, uglify()))
        .pipe(gulpif(!production, sourcemaps.write('./')))
        .pipe(dest(distFiles.distJSPath))
    );
  });
}

```
Resources that help me to solve the problem:

- [Getting import/export working ES6 style using Browserify + Babelify + Gulp = -5hrs of life](https://medium.com/@hey.aaron/getting-import-export-working-es6-style-using-browserify-babelify-gulp-5hrs-of-life-eca7786e44cc)

- [Gulp from Scratch: Compile and Bundle Javascript es6 with Babel](https://www.youtube.com/watch?v=ax0ykSVPufs)

Hope this article helps, feel free to share it with your friends, any feedback will be appreciated :)

Thanks for reading!