Understanding Javascript imports and exports
Tags: javascript, tutorial, webdev
Published: 2022-01-14 09:23:02

# Introduction

If you've spent any time working with Javascript over the past 5 or so years, you've probably come across Javascript Imports and Exports. Introduced as part of the ECMAScript 6 (ES6) specification in June 2015 and now supported in all major browsers, Imports and Exports have shaped the way we build modern Javascript applications. In the beginning, Javascript wasn't designed to be modular. However, 2009 saw the release of Node JS, a popular JavaScript runtime environment that runs outside the browser. Node JS soon began supporting modularity through the CommonJS `require` function and with this developers began searching for solutions to bring modularity to Javascript in the browser.

# What is modularity in Javascript

A Javascript module is a file that can export `variables`, `functions`, and `classes` that can be imported anywhere, allowing developers to share code across multiple files or projects.

# Exporting from Javascript modules

Exporting `variables`, `functions`, and `classes` is made simple in Javascript with the `export` keyword, allowing developers to specify which data/functionality they would like accessed outside the module. Take the following example of a `Dice module`:

```js
const NUMBERS = [1, 2, 3, 4, 5, 6];

function min() {
    return Math.min(...NUMBERS);
}

function max() {
    return Math.max(...NUMBERS);
}

export function roll() {
    return Math.floor((Math.random() * max()) +  min());
}
```

The `Dice module` exports a single function, `rollDice()`, making it the only data/functionality available to be imported elsewhere. In some cases, the developer may decide that more than one piece of data/functionality, or even all data/functionality should be available outside of the `Dice module`. In this case, the developer could simply prefix each `variable` and `function` with the `export` keyword:

```js
export const NUMBERS = [1, 2, 3, 4, 5, 6];

export function min() {
    return Math.min(...NUMBERS);
}

export function max() {
    return Math.max(...NUMBERS);
}

export function roll() {
    return Math.floor((Math.random() * max()) +  min());
}
```

Now every `variable` and `function` in the `Dice module` can be imported individually elsewhere. However, in cases where there is lots of data/functionality to be imported, importing everything individually can become frustrating. Thankfully Javascript also provides developers with the `default` keyword. Using the default keyword, developers can specify a `default export`. In the `Dice module`, the developer could create a `default export` to make all of the module data/functionality available elsewhere with an import-defined prefix:

```js
export default {
    NUMBERS,
    min,
    max,
    roll
}
```

# Importing from Javascript modules 

What and how a developer imports data/functionality from a Javascript module depends entirely on what data/functionality the developer would like to make use of and how the module exports that data/functionality. In the `Dice module`, there is individually exported data/functionality and a `default export`.

## Importing a default export

The syntax for importing `default exports` in Javascript is simple. If the developer was to import the `default export` from the `Dice module` it may look like this:

```js
import Dice from './modules/dice.js';
```
_NOTE: `./modules/dice.js` is the path to the file._

The developer could now reference the `default export` as `Dice`, giving them access to everything in the `default export` object as: `Dice.NUMBERS`, `Dice.min()`, `Dice.max()`, `Dice.roll()`.

To prevent potential name clashes, Javascript allows `default exports` to be imported under any valid name. For example, the `Dice module` could be imported as `Foo`:

```js
import Foo from './modules/dice.js';
```
The developer could now reference the default export as `Foo`, 
giving the them access to everything in the `default export` object as: `Foo.NUMBERS`, `Foo.min()`, `Foo.max()`, `Foo.roll()`.

## Importing an individual data/ functionality

In some cases a module may not provide a `default export`,  the `default export` may not provide the data/functionality the developer wishes to use, or `default export` may return lots of redundant data/functionality. For these situations, Javascript allows the developer to import individual data/functionality. To import individual data/functionality, the developer should wrap the desired exported data/functionality in curly brackets. For example, if the developer would like to import the `NUMBERS` and the `roll()` data/functionality from the `Dice module`:

```js
import { NUMBERS, roll } from './modules/dice.js';
```

This would give the developer access to the `NUMBERS` and `roll()` data/functionality as `NUMBERS` and `roll()`, exactly the names given to them by the module they were exported from. There are times when it's not suitable to use the names given by the module the developer is importing from are not suitable. When importing from multiple modules, the chances of name clashes become increasingly likely, the given names may not be descriptive enough. For these situations, Javascript provides the `as` keyword. The `as` keyword can be used to rename imported individual data/functionality. For example, should the developer want to import the `NUMBERS` data as `DICE_NUMBERS` and the `roll()` functionality as `rollDice`:

```js
import { NUMBERS as DICE_NUMBERS, roll as rollDice } from './modules/dice.js';
```

This would give the developer access to the `NUMBERS` and `roll()` data/functionality as `DICE_NUMBERS` and `rollDice()`.

## Importing and namespacing all individual data/functionality

In some cases, the developer may wish to import all available individual data/functionality from a module, without listing out every individual export. Not all modules will export all of that data/functionality as a `default export`. In these cases the developer can import all module exports under a namespace, using the `*` key. For example, if the developer wished to import all the `Dice module` data/functionality under the namespace `Bar`:

```js
import * as Bar from './modules/dice.js';
```

This would give the developer access to the `NUMBERS`, `min()`, `max()`, and `roll()` data/functionality as `Bar.DICE_NUMBERS`, `Bar.min()`, `Bar.max()`, and `Bar.roll()`.

# Conclusion

Javascript modularity has changed the way developers build web applications. There are several ways to import data/functionality from a module, hopefully, this post provides an insight into when and why to use each import syntax.

If you’ve found this article useful, please follow me on [Medium](https://medium.com/@wearethreebears), Dev.to and/ or [Twitter](https://twitter.com/wearethreebears).