ES6 Modules
Tags: javascript, react, webdev, node
Published: 2020-05-26 10:00:32

ES6 modules use a declarative syntax for importing and exporting, support cyclic dependencies and support an async programmatic loading API for dynamically/conditionally loading modules at runtime.

Future browser APIs will be exposed as ES6 modules instead of global variables, properties of `navigator` or object namespaces such as `Math` and `JSON`.

### Named Exports

Named exports can be individually imported by name and will populate the scope of the importing module.

```js
// math.js
export const PI = Math.PI;
export function add(a,b) => a+b;
export function subtract(a,b) => a-b;
```

```js
// app.js
import {PI,add,subtract} from 'math';
PI; // 3.141592653589793
add(1,1); // 2
```

All named exports can be imported via the wildcard `*` character, in which case they will populate the supplied object namespace.

```js
// app.js
import * as math from 'math';
math.add(1,1); // 2
math.subtract(2,1); // 1
```

Named exports can alternatively be declared separately to the object they're exporting.

```js
// math.js
const PI = Math.PI;
function add(a,b) => a+b;
function subtract(a,b) => a-b;

export {PI,add,subtract};
```

Exported names can be different from the one used internally in the exporting module.

```js
// math.js
const PI = Math.PI;
function add(a,b) => a+b;
function subtract(a,b) => a-b;

export {subtract as minus};
```

And imported names can also be changed.

```js
// app.js
import {subtract as foo} from 'math';
foo(2,1); // 1
```

### Default Exports

Modules can indicate a default object to always be imported when no name is supplied. Default exports are to be favored over named exports since they simplify module APIs by making it unambiguous what to the primary export is. The default export/import syntax is effectively just sugar around a normal named export called `default`.

When importing a default export directly the `{}` named export syntax is not used. Additionally, unlike named exports the imported default export can be named anything you like in the importing module.

```js
// module.js
export default function () {}
```

```js
// app.js
import foo from './module';
foo();
```

Default and named imports can be mixed together on one line.

```js
// module.js
export default function () {}
export function bar () {}
```

```js
// app.js
import foo, {bar} from 'underscore';
```

### Re-Exporting

You can re-export from modules, which can be useful for aggregating many exports from sub modules in a single file. This is often used when exposing a group of exports in a folder's `index.js` file.

```js
// ./stuff/foo.js
export default function () {};
```

```js
// ./stuff/index.js
export {default as foo} from './foo';
export {default as bar} from './bar';
```

```js
// app.js
import {foo} from './stuff';
import * as stuff from 'stuff';
foo();
stuff.foo();
```

### System Module Loader

Modules can be loaded dynamically and conditionally via the loader API exposed by `System`. A common use of `System.import` could be to bootstrap a transpiled ES6 app in a `<script>` tag in a ES5-based browser environment.

```js
System
  .import('some-module')
  .then(someModule => {})
  .catch(error => {});
```
Happy Coding 😃