sindresorhus / p-queue

Promise queue with concurrency control
MIT License
3.41k stars 182 forks source link

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module #144

Closed hyeongyeom closed 2 years ago

hyeongyeom commented 3 years ago

I'm using node v14.16.0. "p-queue": "^7.1.0" version not work with the Error below.

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: D:\Desktop\coding_practice\wocommerce\wooCommerceSyncServer\node_modules\p-queue\dist\index.js require() of ES modules is not supported. require() of D:\Desktop\coding_practice\wocommerce\wooCommerceSyncServer\node_modules\p-queue\dist\index.js from D:\Desktop\coding_practice\wocommerce\wooCommerceSyncServer\src\app.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 D:\Desktop\coding_practice\wocommerce\wooCommerceSyncServer\node_modules\p-queue\package.json.

Even i chaneged node version to v12.14.1. still there an error -> "Error: Cannot find module 'p-queue'"

p-queue ^6.6.2 version worked only in my node app

What's wrong? I spent a lot of time due to this.

pogilvie commented 3 years ago

https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

pogilvie commented 3 years ago

I'm writing a plugin for a larger typescript framework (sfdx cli). The typescript suggestions above blew the whole project up so I just required v6.6.2 and called it a day.

darkadept commented 3 years ago

Same problem here. I'm using babel-node in development and I cannot import ESM modules. Dropping back to 6.x as well. Got the following error:

internal/modules/cjs/loader.js:1080
      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
      ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/zzz/dev/yyy/node_modules/p-queue/dist/index.js
require() of ES modules is not supported.
require() of /home/zzz/dev/yyy/node_modules/p-queue/dist/index.js from /home/zzz/dev/yyy/packages/domain/dist/index.js 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 /home/zzz/dev/yyy/node_modules/p-queue/dist/index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/zzz/dev/yyy/node_modules/p-queue/package.json.
alextes commented 3 years ago

Not quite the same issue but related:

Cannot find module 'p-queue' from 'src/contracts.ts'

Using jest. Jest uses browserify/resolve, and that can't deal with the new ESM export https://github.com/browserify/resolve/issues/222

bawangxx commented 3 years ago

me too

alextes commented 3 years ago

After wrestling with this for a while, moving to ESM (which isn't all rainbows either) or not using this module seems the easiest. Perhaps someone still comes along with a suggestion for how this module could support both, but that is if maintainers are interested.

szmarczak commented 3 years ago

Something like https://github.com/apify/got-cjs maybe?

alextes commented 3 years ago

Yup! Clever. Something just like that. It hardly has anything to do with this library and more with the ecosystem move to ESM in general but this import breaking was one of the reasons I ended up spending more time fiddling with our build than I liked.

agirorn commented 2 years ago

I feel like this move to ESM may not have been completely thought through. At least for the large projects developed in typescript. I for one have been trying to use these ESM modules in typescript projects and just converting them to work with ESM is not a trivial task.

For instance, this close issue in typescript https://github.com/microsoft/TypeScript/issues/40878 where we have to import the '.js'version of a '.ts' girl int source of the '.ts' for local imports. Nobody wants to do this because it is just confusing.

I think that until the ecosystem is ready, then it should have been better to wait or publish them under some tag like esm.

Another option could be to fork the ESM projects and changing them back to commonjs and publishing them so we can still be productive until the exco system recovers.

Richienb commented 2 years ago

p-queue uses ESM now, like stated in the first reply.

paustint commented 11 months ago

For Typescript, I have been using the following which works with node. Otherwise tyepscript was transpiling to a require statement.

import type PQueue from 'p-queue';
....
const { default: PQueue } = await eval("import('p-queue')");
des-psl commented 5 months ago

For Typescript, I have been using the following which works with node. Otherwise tyepscript was transpiling to a require statement.

import type PQueue from 'p-queue';
....
const { default: PQueue } = await eval("import('p-queue')");

@paustint could you please elaborate more your answer? I am getting this error:

image
paustint commented 5 months ago

@des-psl - what error are you getting? The screenshot does not indicate the error message.

You may need to enable allowSyntheticDefaultImports and or esModuleInterop in your tsconfig.

des-psl commented 5 months ago

esModuleInterop

@paustint sorry, forgot to add the error message:

image

I also get that error message when I delete the type keyword. I think the error is related to the 2nd line: import type PQueue from 'p-queue'; const { default: PQueue } = await eval("import('p-queue')"); Perhaps I need to change default: PQueue to another name?

I alreadt added:

  allowSyntheticDefaultImports: true,
  esModuleInterop: true,

To my tsconfig.json file

paustint commented 5 months ago

You cannot import the same thing twice in the global scope, your dynamic import will either need to use a different name or be within a function.

My use-case is just to process a bunch of data in one-off scripts - here is a simplified example

import { writeFileSync } from 'fs';
import type PQueue from 'p-queue';
import { join } from 'path';

const DATA = [
  /// stuff
  {id: '123'}
];

interface Result {
  id: string;
  error?: string;
}

const CONCURRENCY = 50;
// const EVENT_TYPE = 'quote.offering.updated';
const EVENT_TYPE = 'contract.created';

async function main() {
  const timestamp = new Date().getTime();
  const { default: PQueue } = await eval("import('p-queue')");

  const queue: PQueue = new PQueue({ concurrency: CONCURRENCY });

  const results: Result[] = [];

  queue.on('completed', () => {
    writeFileSync(join(__dirname, `./output/${timestamp}-refire-webhook.json`), JSON.stringify(results, null, 2));
  });

  await queue.addAll(DATA.map((row) => () => doWork(row.id, EVENT_TYPE, results)));

  writeFileSync(join(__dirname, `./output/${timestamp}-refire-webhook.json`), JSON.stringify(results, null, 2));
}

async function doWork(id: string, eventType: string, results: Result[]) {
  // do work here
}

main();