Andrey
Andrey

Reputation: 73

Browserify and ES6/ES2015 classes (babel compiler)

I have 2 classes (ES2015 Classes style) in separate files and one App file with require. I want to use this CommonJS modules in browser. Most popular lib is Browserify with Babel compiler for ES2015 syntax (babelify). Example:

Class1.js

class Class1 {
  constructor() {
    this.prop = 1;
  }
  method() {
    console.log(this.prop);
  }
}
module.exports = Class1;

Class2.js

class Class2 {
  constructor() {
    this.prop = 2;
  }
  method() {
    console.log(this.prop);
  }
}
module.exports = Class2;

App.js

var Class1 = require('./Class1');
var Class2 = require('./Class2');
class App {
  constructor() {
    this.class1 = new Class1();
    this.class2 = new Class2();
  }
}
module.exports = App;

gulpfile.js

gulp.task("js", function () {
  browserify({ entries: config.js.appFile, extensions: ['.js'], debug: true })
        .transform(babelify)
        .bundle()
        .pipe(source(config.js.appMinFile))
        .pipe(gulp.dest('.'));
});

The problem in result app.js. It contains duplicate code for each classes in each modules.

var _createClass = function () { ... }
function _classCallCheck(instance, Constructor) { ...}
function _possibleConstructorReturn(self, call) { ... } //not for example above but can exists
function _inherits(subClass, superClass) { ... } //not for example above but can exists

How to remove this duplicate code with sourcemap support for source js files?

I tried Browserify all js files in one without Babelify transform, then compile result with Babel. It works without duplicate code but sourcemap will incorrect.

Upvotes: 1

Views: 1899

Answers (1)

loganfsmyth
loganfsmyth

Reputation: 161457

The simple answer is that you should npm install babel-plugin-transform-runtime babel-runtime and then include

"plugins": ["transform-runtime"]

in your .babelrc alongside your "presets": ["es2015"] configuration.

The exact answer depends on how you want your polyfill functions to work. Babel provides babel-polyfill as a way to globally load a polyfill that will add ES6 library functions throughout your application. However this can conflict with the default behavior of transform-runtime above, which will instead attempt to point references to globals back at the babel-runtime module. This means you could accidentally end up with two copies of the same polyfilled APIs loaded.

  1. If you want/need to use babel-polyfill because it globally provides tons of standard ES6 functionality, including global prototype methods like Array.prototype.includes, then you should add additional params to your plugin:

    "plugins": [
      ["transform-runtime", {polyfill: false, regenerator: false}],
    ]
    
  2. If you don't want to use a globally-polluting polyfill like babel-polyfill, you can use the polyfilling logic in babel-runtime instead. This can be important if for instance you are writing a standalone library and don't want to make all your users load babel-polyfill for you, or change globals from the library, which is a bad idea.

    "plugins": [
      "transform-runtime",
    ]
    

Upvotes: 2

Related Questions