JavaScript Modules
Tags: javascript
Published: 2023-03-06 19:27:26

---
title: JavaScript Modules
published: true
date: 2023-01-12 08:00:00 UTC
tags: JavaScript
canonical_url: https://www.90-10.dev/js-modules/
---

As our JavaScript code grows in site, there comes a times where including one file in not enough- here we're having a look at how to structure code across multiple files using modules.

## Enable modules

Given an `index.html` file that includes a `app.js` file using a `script` tag, to enable module, we'll have to include `type="module"`:

```
<html>
  <head>...</head>
  <body>
    ...
    <script src="app.js" type="module"></script>
  </body>
</html>

```

_index.html_

## Default Import/Export

Now, can include functions defines in other files:

```
import f1 from './dependency.js';
...
f1();

```

_app.js_

... where f1 is exported from within the dependency:

```
function f1() {
  ...
}
export { f1 as default };

```

_dependency.js_

## Named Import/Export

An alternative that is usually used when multiple 'transfers' are required is using named exports/imports:

```
function f1() {
  ...
}
function f2() {
  ...
}
export { f1, f2};

```

_dependency.js_

On import, the names must match the exact names from export (order not relevant):

```
import {f1, f2} from './dependency.js';
...
f1();

```

_app.js_

### Renamed Export

Function can be renamed as part of the export:

```
function f1() {
  ...
}
function f2() {
  ...
}
export { f1, f2 as f3};

```

_dependency.js_

Now, it's imported as `f3`:

```
import {f1, f3} from './dependency.js';
...
f3();

```

_app.js_

### Renamed Import

Function can also be renamed as part of the import:

```
function f1() {
  ...
}
function f2() {
  ...
}
export { f1, f2};

```

_dependency.js_

Now, it's imported as `f3`:

```
import {f1, f2 as f3} from './dependency.js';
...
f3();

```

_app.js_

### Inline exports

The exports can also happen inline for each function that needs it:

```
export function f1() {
  ...
}
export function f2() {
  ...
}

```

_dependency.js_

## Combined imports: Default & Named

Both of the previous methods can be combined for some interesting results:

```
function f1() {
  ...
}
function f2() {
  ...
}
export { f1 as default, f2};

```

_dependency.js_

Now, the import might look a bit strange:

```
import f1, {f2} from './dependency.js';
```

_app.js_

## Passthrough Exports

Say we have 2 dependencies and we don't want to have to import both.

Given a second dependency:

```
function f2() {
  ...
}
export { f2 };

```

_dependency2.js_

We can simply "pass it through" in the first dependency:

```
function f1() {
  ...
}
export { f1 };
export { f2 } from './dependency2.js';

```

_dependency1.js_

Now `app.js` will only have to import from one dependency:

```
import {f1, f2} from './dependency1.js';
```

_app.js_

## Import all

A great technique that sames keystrokes on import is the ability to import all functions together.

Given:

```
function f1() {
  ...
}
function f2() {
  ...
}
export { f1, f2};

```

_dependency.js_

All exports can be imported together, but the usage is slightly different:

```
import * as dependant from './dependency.js';
dependant.f1();

```

_app.js_

## Finally

Classes can also be exported and imported.

Unfortunately, modules are not available in IE (see [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)) but are in Edge.

To achieve backward compatibility and avoid multiple HTTP requests in a production environment, we should probably use a module bundler such as [Webpack](https://webpack.github.io/) or [Babel](https://babeljs.io/).