Notes on ES Modules with Chantastic
Tags: javascript, esm, node, esbuild
Published: 2021-03-12 21:56:31

---
canonical_url: "https://ajcwebdev.com/es-module-notes-with-chantastic/"
description: "A collection of examples demonstrating static and dynamic imports, export lists, and import aliases."
---

## Outline

- [Introduction](#introduction)
  - [Index Main File](#index-main-file)
  - [Prepared Module Files](#prepared-module-files)
  - [Assignments](#assignments)
- [Import a Module from the File System](#import-a-module-from-the-file-system)
  - [Leaky Modules](#leaky-modules)
  - [Add Globally Executing Code to a Module](#add-globally-executing-code-to-a-module)
- [Import a Module Dynamically](#import-a-module-dynamically)
  - [Change the Static Import to a Dynamic Import](#change-the-static-import-to-a-dynamic-import)
- [Export Lists](#export-lists)
  - [Add a Variable and Function Declaration to the Module](#add-a-variable-and-function-declaration-to-the-module)
  - [Use an Export List to Export a Function](#use-an-export-list-to-export-a-function)
- [Alias or Rename Imports and Exports](#alias-or-rename-imports-and-exports)
  - [Rename a Function while Exporting](#rename-a-function-while-exporting)

## Introduction

ES Modules (JavaScript Modules, if you like) help us structure, organize and isolate code. [These examples](https://github.com/chantastic/esmodule-reference-course) focus on the ESM features available in a Node environment such as dynamic modules, export lists, and module aliasing.

Most JS apps in early 2021 are still bundled before being sent to the browser. Features covered here are common to the latest LTS Node environments for most popular Node bundling tools like Webpack, Rollup, and esbuild.

### Index Main File

* This is where all exercises are run
* Examples in `readme.md` can be copy/pasted into `index.js`

### Prepared Module Files

* The names relate to the type of content inside
* Various examples might use these prepared modules to explore a concept

### Assignments

* `./modules/assignment.mjs` is an empty module.

## Import a Module from the File System

Modules are imported using the `import` keyword and a string path to that module. This is predominantly done at the opening of a file. We can import any module that exists on the file system. Import the `assignment.mjs` module using the `import` keyword and file path:

```javascript
// index.js

import "./modules/assignment.mjs"
```

### Leaky Modules

The first thing to know about modules is that they leak. They don't perfectly encapsulate all code. Global code is global code, even if in a module. This might sounds bad (and it can be) but it's an important feature.

### Add Globally Executing Code to a Module

Globally executing code can be `console.log("booo!!")` or an assignment like `global.leak = "oh no!"`.

```javascript
// modules/assignment.mjs

console.log("sah dude")
global.leak = "oops"
```

```javascript
// index.js

import "./modules/assignment.mjs"

console.log(global.leak)
```

```
sah dude
oops
```

## Import a Module Dynamically

The `import` keyword has two variants: static and dynamic. You can change a static import to a dynamic import by adding parenthesis around the path string.

```javascript
import "./modules/assignment.mjs" // static
import("./modules/assignment.mjs") // dynamic
```

### Change the Static Import to a Dynamic Import

A dynamic `import` returns a `Promise`, so try handling that promise using `await`.

```javascript
// index.js

await import("./modules/assignment.mjs")

console.log(global.leak)
```

Or use `.then()` to resolve the `Promise`.

```javascript
// index.js

import("./modules/assignment.mjs")
  .then(() => console.log(global.leak))
```

```
sah dude
oops
```

## Export Lists

Global code is executed at `import` but variables and function declarations are not. Even though a function or variable might exist in an imported module, it can't be accessed outside of that module.

### Add a Variable and Function Declaration to the Module

```javascript
// modules/assignment.mjs

let fallbackName = "there"

function greet(name = fallbackName) {
  return `Hey, ${name}!`
}
```

### Use an Export List to Export a Function

We can export anything defined in our module by adding it to the comma separated `export` list.

```javascript
// modules/assignment.mjs

let fallbackName = "there"

function greet(name = fallbackName) {
  return `Hey, ${name}!`
}

export { fallbackName, greet }
```

Anything exported can also use the same list syntax, `{}`, for `import`. Importing specific imports from a module requires the `from` keyword before the path string.

```javascript
// index.js

import { greet } from "./modules/assignment.mjs"

console.log(greet())
```

```
Hey, there!
```

`export` list is commonly at the end of a file to guarantee that everything exported — or referenced — already exists. Now with an `export` list, export and import just the `greet` function.

```javascript
// modules/assignment.mjs

let fallbackName = "dude"

function greet(name = fallbackName) {
  return `Sah, ${name}`
}

export { greet }
```

`greet` still has access to `fallbackName`, even though `fallbackName` isn't exported.

```javascript
// index.js

import { greet } from "./modules/assignment.mjs"

console.log(greet())
```

```
Sah, dude
```

## Alias or Rename Imports and Exports

Modules might not share object syntax with modules but they still allow for aliasing (or renaming) of variables and functions using the `as` keyword.

```javascript
// modules/assignment.mjs

export { aGoodLocalName as aBetterExportedName }
```

It works identically on both the `import` and `export` sides.

```javascript
// index.js

import {
  aBetterExportedName as anEvenBetterContextualName
} from "./modules/assignment"
```

### Rename a Function while Exporting

At import, use the new function name you've exported and then rename it back to `greet` at `import`.

```javascript
// modules/assignment.mjs

let fallbackName = "dude";

function greet(name = fallbackName) {
  return `Sah, ${name}`
}

export { greet as sahDude }
```

```javascript
// index.js

import { sahDude as greet } from "./modules/assignment.mjs"

console.log(greet())
```

```
Sah, dude
```