Reputation: 734
I am trying to import the package p-limit into my typescript project. When trying to run the project using tsc && node serve.js
, I run into the error below.
Im stuck at this for a few hours now...
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /project/node_modules/p-limit/index.js
require() of ES modules is not supported.
require() of /project/node_modules/p-limit/index.js from /project/dist/services/file.ts is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /project/node_modules/p-limit/package.json.
This piece of code in file.ts
is causing the issue:
import pLimit from 'p-limit';
const limit = pLimit(1);
tsconfig.json
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"resolveJsonModule": true,
"esModuleInterop": true,
"rootDir": "src",
"outDir": "dist",
"sourceMap": true,
"experimentalDecorators": true,
"types": [
"node",
"express"
],
"strictNullChecks": true
},
"files": [
"./node_modules/@types/node/index.d.ts",
"./node_modules/p-limit/index.d.ts"
],
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
Node version: v14.18.0
Upvotes: 16
Views: 24986
Reputation: 195
import()
to require()
which may not able to load the ESM module.You cannot directly import a pure ESM module in a CommonJS project, in the same way you import other dependencies.
Although you are using import
, the TypeScript compiler does compile that to require
, and therefor you get the error you should be using import
.
You can import an ESM module in CommonJS project using dynamic import, using JavaScript, this does not work for TypeScript.
(async () => {
// This is the way to load an ESM module in a JavaScript / CommonJS project
const {default: pLimit} = await import('p-limit'); // dynamic import
const limit = pLimit(1);
})();
When you work in TypeScript, and you try the above code, you will directly run into the next problem, as the TypeScript compiler also transpiles the dynamic import (import()
) to require()
. That problem is described here: Dynamically load ESM module in CJS package in TypeScript.
In line with the recommendation I gave in that problem, this a way to resolve your issue:
You need to add load-esm
to your project (a utility I wrote).
npm add load-esm
Now you can dynamically load the pure ESM plimit
in your TypeScript code:
import {loadEsm} from 'load-esm';
(async () => {
const { default: pLimit } = await loadEsm<typeof import('p-limit')>('p-limit'); // dynamic-import of pure ESM module
const limit = pLimit(1);
})();
Upvotes: 0
Reputation: 11
Starting from version 22.12.0
, nodejs is able to require()
ecmascript modules (ESM) with some constraints, you can check the documentation and constraints here.
In this case, p-limit
can be loaded using this feature
Using [email protected]
(current latest LTS version)
npm init && npm i -DE [email protected] [email protected] @types/node
// test.ts
import pLimit from "p-limit"
const throttle = pLimit(2)
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms))
const run = async () => {
console.log("== START ==")
const promises = Array(20).fill(0).map((_, idx) => throttle(async () => {
await delay(1000)
console.log("done", idx)
}))
await Promise.all(promises)
console.log("== FINISH ==")
}
run()
# transpile to js
tsc --module commonjs test.ts
# run
node test.js
Upvotes: 1
Reputation: 776
p-limit 4.0.0 and above are now ESM only. You can downgrade p-limit to 3.1.0 which is commonjs and it should work fine.
This package is now pure ESM. Please read this.
https://github.com/sindresorhus/p-limit/releases/tag/v4.0.0
Alternatively you can switch your project from CJS to ESM, but that's a larger issue.
https://nodejs.org/api/esm.html
Upvotes: 21