How to convert a CJS module to an ESM
Published: 2022-10-21 09:44:20

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

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

Since **Node v14** , there are two kinds of modules, **CommonJS Modules (CJS)** and **EcmaScript Modules (ESM)**. EcmaScript Modules (ESM) were introduced as part of ES6 (EcmaScript 2015). The main goal was for module includes to be statically analyzable, so browsers would be able to pre-parse out imports. This behaviour is similar to collecting all `<script>` tags as the web page loads.

It took more than three years for major browsers to implement this retrofitting of a static module system into a dynamic language. And even longer for ESM to be implemented in NodeJS, because of interoperability with the existing CJS module system, though there are still some issues.

The main difference between CJS and ESM is that **CJS loads every module synchronously** , and **ESM loads every module asynchronously**.

There are also two types of ESM: native ESM and "transpiled ESM". Transpiled ESM is ESM-like syntax that would be typically be transpiled with Babel. The syntax looks similar, but the behaviour can vary. "Transpiled ESM" compiles to CommonJS in Node and will be compiled in the browser using a bundled synchronous loader. This means, that "transpiled ESM" loads modules synchronously, native ESM loads modules asynchronously.**A Node application (or module) can contain CJS and ESM files.**

Let's convert the module created in [How to create a CSJ module](https://www.mariokandut.com/how-to-create-a-csj-module/).

The CSJ module contains this code:

```
'use strict';

const toUpper = str => {
  if (typeof str === 'symbol') str = str.toString(); // convert to string if symbol is used as input
  str += '';
  return str.toUpperCase();
};

module.exports = { toUpper };
```

To convert it to an ESM module, the only we have to do change the file extension from `.js` to `.mjs`. If you are on linux you can use the `mv` command.

```
mv format.js format.mjs
```

CJS modules modify the `module.exports` object, in ESM its native syntax. Hence, to create a named export, we can just use the `export` keyword.

Let's update our module:

```
export const toUpper = str => {
  if (typeof str === 'symbol') str = str.toString(); // convert to string if symbol is used as input
  str += '';
  return str.toUpperCase();
};
```

The `'use strict'` pragma to enforce strict mode is also not needed anymore, since ESM executes in strict-mode.

That's it for converting CSJ to ESM. There is only one thing, try to run the node application with `node index`. You will see an error.

```
internal/modules/cjs/loader.js:948
    throw new ERR_REQUIRE_ESM(filename);
    ^
```

This error occurs because the `require` function will not automatically resolve a filename without an extension `('./format')` to an `.mjs` extension.

Ok, so let's fix this and try again.

```
node -p "require('./format.mjs')"
```

We will get an error again.`Error [ERR_REQUIRE_ESM]: Must use import to load ES Module.`

The major difference between CSJ and ESM, is that CJS is synchronous. CJS cannot require ESM since that would break the synchronous constraint, but ESM can import CJS.

There is a way around this constraint with dynamic import. Have a look at this article [How to dynamically load an ESM Module in CJS](https://www.mariokandut.com/how-to-dynamically-load-an-esm-module-in-cjs/).

## [<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

- Since **Node v14** , there are two kinds of modules, **CommonJS Modules (CJS)** and **EcmaScript Modules (ESM)**.
- The main difference between CJS and ESM is that **CJS loads every module synchronously** , and **ESM loads every module asynchronously**.
- To convert a CSJ module to ESM, change the file ending to `.mjs` and use the `export` keyword instead of `module.exports`.
- CJS cannot require ESM since that would break the synchronous constraint, but ESM can import CJS.
- Use dynamic import for importing ESM in CSJ.

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),[JSNAD](https://trainingportal.linuxfoundation.org/),[CommonJS](https://requirejs.org/docs/commonjs.html)