How to dynamically load ESM in CJS
© https://nodejs.org/en/

How to dynamically load ESM in CJS

Use dynamic import() as workaround

By Mario Kandut

Europe’s developer-focused job platform

Let companies apply to you

Developer-focused, salary and tech stack upfront.

Just one profile, no job applications!

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.

💰 The Pragmatic Programmer: journey to mastery. 💰 One of the best books in software development, sold over 200,000 times.

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.

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.

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, 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.

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.

If you want to know more about Node, have a look at these Node Tutorials.

References (and Big thanks):

NodeJS, v8.dev, TC39, JSNAD, CommonJS

More node articles:

How to create a web server in Node.js

How to dynamically load ESM in CJS

How to convert a CJS module to an ESM

How to create a CJS module

How to stream to an HTTP response

How to handle binary data in Node.js?

How to use streams to ETL data?

How to connect streams with pipeline?

How to handle stream errors?

How to connect streams with pipe?

What Is a Node.js Stream?

Handling Errors in Node (asynchronous)

Handling Errors in Node.js (synchronous)

Introduction to errors in Node.js

Callback to promise-based functions

ETL: Load Data to Destination with Node.js

ETL: Transform Data with Node.js

ETL: Extract Data with Node.js

Event Emitters in Node.js

How to set up SSL locally with Node.js?

How to use async/await in Node.js

What is an API proxy?

How to make an API request in Node.js?

How does the Event Loop work in Node.js

How to wait for multiple Promises?

How to organize Node.js code

Understanding Promises in Node.js

How does the Node.js module system work?

Set up and test a .env file in Node

How to Use Environment Variables in Node

How to clean up node modules?

Restart a Node.js app automatically

How to update a Node dependency - NPM?

What are NPM scripts?

How to uninstall npm packages?

How to install npm packages?

How to create a package.json file?

What Is the Node.js ETL Pipeline?

What is data brokering in Node.js?

How to read and write JSON Files with Node.js?

What is package-lock.json?

How to install Node.js locally with nvm?

How to update Node.js?

How to check unused npm packages?

What is the Node.js fs module?

What is Semantic versioning?

The Basics of Package.json explained

How to patch an NPM dependency

What is NPM audit?

Beginner`s guide to NPM

Getting started with Node.js

Scroll to top ↑