DEV Community

Charlie @ 90-10.dev
Charlie @ 90-10.dev

Posted on • Originally published at 90-10.dev on

JavaScript 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>

Enter fullscreen mode Exit fullscreen mode

index.html

Default Import/Export

Now, can include functions defines in other files:

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

Enter fullscreen mode Exit fullscreen mode

app.js

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

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

Enter fullscreen mode Exit fullscreen mode

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};

Enter fullscreen mode Exit fullscreen mode

dependency.js

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

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

Enter fullscreen mode Exit fullscreen mode

app.js

Renamed Export

Function can be renamed as part of the export:

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

Enter fullscreen mode Exit fullscreen mode

dependency.js

Now, it's imported as f3:

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

Enter fullscreen mode Exit fullscreen mode

app.js

Renamed Import

Function can also be renamed as part of the import:

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

Enter fullscreen mode Exit fullscreen mode

dependency.js

Now, it's imported as f3:

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

Enter fullscreen mode Exit fullscreen mode

app.js

Inline exports

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

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

Enter fullscreen mode Exit fullscreen mode

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};

Enter fullscreen mode Exit fullscreen mode

dependency.js

Now, the import might look a bit strange:

import f1, {f2} from './dependency.js';
Enter fullscreen mode Exit fullscreen mode

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 };

Enter fullscreen mode Exit fullscreen mode

dependency2.js

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

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

Enter fullscreen mode Exit fullscreen mode

dependency1.js

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

import {f1, f2} from './dependency1.js';
Enter fullscreen mode Exit fullscreen mode

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};

Enter fullscreen mode Exit fullscreen mode

dependency.js

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

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

Enter fullscreen mode Exit fullscreen mode

app.js

Finally

Classes can also be exported and imported.

Unfortunately, modules are not available in IE (see MDN docs) 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 or Babel.

Top comments (0)