How to dynamically load ESM in CJS
Published: 2022-10-21 09:44:30

---
title: How to dynamically load ESM in CJS
published: true
date: 2022-02-21 00:00:00 UTC
tags: 
canonical_url: https://www.mariokandut.com/how-to-dynamically-load-an-esm-module-in-cjs/
---

> This article is based on **Node v16.14.0**.

The main distinction between ESM and CJS is the loading of modules. ESM loads asynchronous and CJS loads synchronous. There are limitations in interoperability, while ESM can import CJS, CJS cannot require ESM, because it would break the synchronous constraint.

For modules to work in both worlds (ESM and CJS), they would have to expose a CJS interface, but **ESM is JavaScripts native module system**. As you can see, this is quite a tension point in the node ecosystem.

There is a workaround to asynchronously load an ESM module for use in a CJS module, it is based on **dynamic import**.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#dynamic-import)Dynamic `import()`

Dynamic import() introduces a new function-like form of `import`. `import(moduleSpecifier)` returns a promise for the module namespace object, which is created after fetching, instantiating, and evaluating all the module’s dependencies, as well as the module itself. Read more about it on [v8.dev](https://v8.dev/features/dynamic-import#dynamic).

The sample code below (from the v8 docs), shows how to dynamically load the module `utils.mjs`.

```
<script type="module">
  const moduleSpecifier = './utils.mjs';
  import(moduleSpecifier).then(module => {
    module.default();
    // → logs 'Hi from the default export!'
    module.doStuff();
    // → logs 'Doing stuff…'
  });
</script>
```

In the previous article [How to convert a CJS module to an ESM](https://www.mariokandut.com/how-to-convert-a-cjs-module-to-an-esm-module-in-node/), we were converting a CJS to an ESM and were not able to load it, because of the synchronous constraint. Let's fix this.

Open the `index.js` file and load the module `format.mjs` dynamically, since `import` returns a promise we can use `then`, though`async/await` can be used as well.

```
import('./format.mjs').then(format => {
  console.log(format.toUpper('this will be uppercase'));
});
```

Try to run it with `node index.js`. You should not get an error and the output should be `THIS WILL BE UPPERCASE`.

Using dynamic import to load an ESM module into CJS can force a change to the application API, a synchronous function becomes asynchronous. In some cases it might be worth to consider changing the entire project to an ESM package.

## [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#tldr)TL;DR

- Dynamic import enables loading of ESM into CJS.
- Using dynamic import can change the application API (sync to async).

Thanks for reading and if you have any **questions** , use the **comment** function or **send me a message** **[@mariokandut](https://www.twitter.com/mariokandut)**.

If you want to know more about **[Node](https://www.mariokandut.com/tags/node)**, have a look at these [Node Tutorials](https://www.mariokandut.com/tags/node).

### [<svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>](#references-and-big-thanks)References (and Big thanks):

[NodeJS](https://nodejs.org/api/esm.html),[v8.dev](https://v8.dev/features/dynamic-import#dynamic),[TC39](https://github.com/tc39/proposal-dynamic-import),[JSNAD](https://trainingportal.linuxfoundation.org/),[CommonJS](https://requirejs.org/docs/commonjs.html)