Conditional export in ES2015

Dan Dascalescu picture Dan Dascalescu · Sep 20, 2016 · Viewed 18.8k times · Source

Let's say you're developing a polyfill and don't want to shim a class if it already exists in the browser. How can this be done in ES6? The following is not valid because exports is not a statement:

if (typeof Foo === 'undefined') {
  export class Foo { ... }
}

If the condition above evaluates to false, the importing script should get the browser built-in.

Answer

Estus Flask picture Estus Flask · Sep 20, 2016

export should be static. For conditional exports CommonJS modules and exports can be used.

It should be handled with ES6 modules this way:

export let Foo;

if (window.Foo === undefined) {
  Foo = class Foo { ... }
} else {
  Foo = window.Foo;
}

For platform-independent solution (this may not be equal to global in transpiled code) window can be replaced with

const root = (() => eval)()('this');
if (root.Foo === undefined) {
...

This exploits binding feature of ES6 modules which was designed this way to handle cyclic dependencies and explained greatly here.

The code above transpiles to

...
var Foo = exports.Foo = void 0;

if (window.Foo === undefined) {
  exports.Foo = Foo = function Foo() {
    _classCallCheck(this, Foo);
  };
} else {
  exports.Foo = Foo = window.Foo;
}

In this case export is not conditional, but Foo value that is bound to this export is conditional.