Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional export in ES2015

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.

like image 339
Dan Dascalescu Avatar asked Sep 20 '16 00:09

Dan Dascalescu


People also ask

How can I conditionally import an ES6 module?

To conditionally import an ES6 module with JavaScript, we can use the import function. const myModule = await import(moduleName); in an async function to call import with the moduleName string to import the module named moduleName . And then we get the module returned by the promise returned by import with await .

How do I export multiple functions?

To export multiple functions in JavaScript, use the export statement and export the functions as an object. Alternatively, you can use the export statement in front of the function definitions. This exports the function in question automatically and you do not need to use the export statement separately.

How do I export multiple variables in JavaScript?

Use named exports to export multiple variables in JavaScript, e.g. export const A = 'a' and export const B = 'b' . The exported variables can be imported by using a named import as import {A, B} from './another-file. js' . You can have as many named exports as necessary in a file.


3 Answers

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.

like image 154
Estus Flask Avatar answered Oct 12 '22 19:10

Estus Flask


export syntax must be at the top-level scope of a module because you are declaring what exports exist. You are free to conditionally assign them a value though, like

export let Foo = global.Foo;

if (typeof Foo === 'undefined'){
    Foo = class { ... }
}
like image 13
loganfsmyth Avatar answered Oct 12 '22 18:10

loganfsmyth


The above methods did not work well for me with Webpack. Conditionally bailing out caused Webpack warnings which increased bundle size by 20KB before minification.

Webpack plugins have optimisation which kicks in for production builds. The following code worked for me without increasing the bundle size.

let comp = null;
if (process.env.NODE_ENV) {
  comp = require('./MyDevComp').default;
}

The above conditional require did not increase the bundle size for production builds.

like image 2
vijayst Avatar answered Oct 12 '22 18:10

vijayst