[Fixed] NPM / Node Error err_require_esm
Ever saw the error err_require_esm? This is due to ESM-only modules. Check out this post on how to fix it!
Jan 24, 2023 | Read time 11 minutes🔔 Table of contents
Introduction
I was working through a few NPM package upgrades and saw a strange error that came up: Error [ERR_REQUIRE_ESM]
This was during my upgrade of a recent version of node-fetch:
C:\SECRET\<USER>\dist\Util\retreiveMovies.js:17
const node_fetch_1 = __importDefault(require("node-fetch"));
^
Error [ERR_REQUIRE_ESM]: require() of ES Module C:\SECRET\<USER>\node_modules\node-fetch\src\index.js from C:\SECRET\<USER>\dist\Util\retreiveMovies.js not supported.
Instead change the require of index.js in C:\SECRET\<USER>\dist\Util\retreiveMovies.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (C:\SECRET\<USER>\dist\Util\retreiveMovies.js:17:38)
at Object.<anonymous> (C:\SECRET\<USER>\dist\Util\index.js:15:14)
at Object.<anonymous> (C:\SECRET\<USER>\dist\Commands\BotOwner\startAutoUpdate.js:4:16)
at C:\SECRET\<USER>\dist\Client\index.js:61:41
at Array.forEach (<anonymous>)
at ExtendedClient.<anonymous> (C:\SECRET\<USER>\dist\Client\index.js:58:48)
at Generator.next (<anonymous>)
at C:\SECRET\<USER>\dist\Client\index.js:27:71
at new Promise (<anonymous>)
at __awaiter (C:\SECRET\<USER>\dist\Client\index.js:23:12)
at ExtendedClient.init (C:\SECRET\<USER>\dist\Client\index.js:51:16)
at Object.<anonymous> (C:\SECRET\<USER>\dist\index.js:19:4) {
code: 'ERR_REQUIRE_ESM'
}
The NPM error ERR_REQUIRE_ESM is caused by the package that we are trying to use is a ESM module (ECMAScript module) and we are trying to use it with the CommonJS pattern of require()
syntax.
If a NPM package is written as a ESM modules we should use it with import/export keywords. It will not be compatible with the CommonJS syntax of require()
.
To fix this error, you should update your code to use the import syntax when importing ESM modules. For example, instead of using:
const myModule = require('my-module')
,
we should update the code to use the import keyword:
import myModule from 'my-module'
Variant of the same ERR_REQUIRE_ESM error could like the below too:
Error [ERR_REQUIRE_ESM]: require() of ES Module C:\node_modules\log-update\index.js from C:\src\utils\files\log.utils.js not supported.
Instead change the require of index.js in C:\src\utils\files\log.utils.js to a dynamic import() which is available in all CommonJS modules.
courses\node_modules\@babel\node\lib\_babel-node.js:176:21) {
code: 'ERR_REQUIRE_ESM'
}
npm ERR! code 1
npm ERR! path C:\Web
npm ERR! command failed
npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c babel-node src/scripts/initiate.script.js
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\AppData\Local\npm-cache\_logs\2022-01-01T17_56_21_202Z-debug-0.log
Whats this ESM?
ECMAScript modules (ESM) was introduced in ECMAScript version 6 (ES6), which was officially standardized in June 2015.
It was the first time that JavaScript had a standardized way to work with modules, which prior to that point had been done using non-standardized methods such as CommonJS or AMD. ESM provides a more efficient and simpler way to share and reuse code across different files and modules, and it is now supported in modern browsers and Node.js.
Here is an example of using ECMAScript modules (ESM) in JavaScript:
File: math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
File: index.js
import { add, subtract } from './math.js';
console.log(add(1, 2)); // 3
console.log(subtract(5, 3)); // 2
In the above example, we have two files math.js and index.js. In math.js file, we have two functions add and subtract which are exported using the export keyword. In the index.js file, we are importing these functions using the import keyword and then using them to perform some operations. Note that the imported functions can be used as any other normal function in javascript, and you don’t need to use a callback or a promise to get the result after the module is imported.
It’s worth noting that you need to run your javascript code with an ESM compatible runtime, for example, Node.js version 14 or above supports ESM natively, you can use the –experimental-modules flag to run ESM code on earlier versions of Node.js.
What about CommonJS?
CommonJS is a module system used in JavaScript for the server-side development. It allows for the creation of modules that can be exported and imported into other files. This allows for the organization of code into smaller, reusable chunks, making it easier to manage and maintain.
Here’s an example of a CommonJS module:
// myModule.js
const myFunction = () => {
console.log("Hello, World!");
}
module.exports = { myFunction }
In the above example, the myFunction is exported from the module using the module.exports object.
To import the module in another file, you would use the require() function:
// main.js
const myModule = require('./myModule');
myModule.myFunction(); // Outputs "Hello, World!"
In the above example, the require() function is used to import the myModule module. The myFunction function is then invoked by using the dot notation.
It’s important to note that CommonJS is mostly used in Node.js environment and it is synchronous in nature which means it will block the execution of the script until the required module is loaded.
Node-fetch giving ERR_REQUIRE_ESM
Node-fetch is pretty awesome NPM package that tries to simulate the fetch
keyword in the browser for Node JS applications. This just makes it easy to make HTTP requests in a similar way as you would in the browser.
As part of version 3.x of node-fetch, they converted it over as ESM module instead of previous versions using CommonJS. This would mean that you are not able to import it with require!
To fix the err_require_esm error with node-fetch we have two options:
- downgrade and use node-fetch version 2 to continue using the require() syntax
- convert your project to be ESM compatible - using the import keyword!
- specify “type”:“module” in package.json
So for the new version 3.x we have to use the import keyword:
import fetch from 'node-fetch';
const response = await fetch('https://github.com/');
const body = await response.text();
console.log(body);
Tip: Make sure you have at least Node version 12.20.0.
We can install node-fetch with the NPM command:
npm install node-fetch
node-fetch version 3.x will drop support for Node.js 4, 6, 8, and 10, so make sure you update the to the latest supported version!
Previously we can get away with CommonJS syntax like so:
const fetch = require('node-fetch');
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))
What if I need to use node-fetch with require()?
If you really need to use node-fetch with the CommonJS syntax using require()
, you should stick with versions 2.x
We can install it with NPM using:
npm install node-fetch@2
Additionally, we can use the async import()
method that is available from CommonJS to load node-fetch
asynchronously:
// mod.cjs
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error))
Node versions with ERR_REQUIRE_ESM
ESM modules are support from Node 12 onwards.
Specifically, you also need to make sure you’re on the latest minor version of Node.js.
At minimum Node.js 12.20, 14.14, or 16.0.
ERR_REQUIRE_ESM for Chalk
Chalk is a pretty cool library to have colorful console logs. The problem is that with the latest version of Chalk (version 5) - it is a ESM-only module.
We get the error of ERR_REQUIRE_ESM for Chalk is because we are importing the package but still using the require()
CommonJS syntax instead of ESM sytax with the import keyword!
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/<username>/Documents/CodeX/NPM/node_modules/chalk/source/index.js
from /Users/<username>/Documents/CodeX/NPM/main.js not supported.
Instead change the require of index.js in /Users/<username>/Documents/CodeX/NPM/main.js to
a dynamic import() which is available in all CommonJS modules. at Object. (/Users/<username>/Documents/CodeX/NPM/main.js:1:15) { code: 'ERR_REQUIRE_ESM' }
To fix the ERR_REQUIRE_ESM for Chalk we either:
- Update your code to use import keyword or
- Keep using the previous version of Chalk
1. Update your code to use import keyword
Edit your package.json file to allow ESM imports. Add the following in your package.json file:
{
"type": "module"
}
Load Chalk with the import keyword, as so:
import chalk from "chalk";
2. Keep using the previous version of Chalk
Follow these steps to downgrade.
Replace your existing chalk key with the following in your package.json file:
{
"dependencies": {
"chalk": "4.1.2"
}
}
Then, run the following command to install Chalk from your package.json file. Make sure to run this in the directory in which your package.json file is in!
npm install chalk
Use the require() statement like normal.
const chalk = require("chalk");
Checklist on converting CommonJS modules over to ESM
- Add “type”: “module” to your package.json.
- Replace “main”: “index.js” with “exports”: “./index.js” in your package.json.
- Update the “engines” field in package.json to Node.js 14: “node”: “>=14.16”. (Excluding Node.js 12 as it’s no longer supported)
- Remove ‘use strict’; from all JavaScript files.
- Replace all require()/module.export with import/export.
- Use only full relative file paths for imports: import x from ‘.'; → import x from ‘./index.js’;.
- Optional but recommended, use the node: protocol for imports.
Summary
In this post I went over the node error of ERR_REQUIRE_ESM. The NPM error of ERR_REQUIRE_ESM is usually due to the fact that the package we are trying to import is a ESM-only module and we are using the CommonJS syntax with the require() to import it!
To fix this ERR_REQUIRE_ESM error, we have a few options - convert our code base over to use ESM imports, upgrade our node version the minimum version of Node >= 12.20, or downgrad and keep using the CommonJS packages!