简体   繁体   English

错误:导入 node-fetch 时不支持 ES 模块的 require()

[英]Error: require() of ES modules is not supported when importing node-fetch

I'm creating a program to analyze security camera streams and got stuck on the very first line.我正在创建一个程序来分析安全摄像头流并卡在第一行。 At the moment my.js file has nothing but the import of node-fetch and it gives me an error message.目前 my.js 文件只有 node-fetch 的导入,它给了我一条错误消息。 What am I doing wrong?我究竟做错了什么?

Running Ubuntu 20.04.2 LTS in Windows Subsystem for Linux.在 Linux 的 Windows 子系统中运行 Ubuntu 20.04.2 LTS。

Node version:节点版本:

user@MYLLYTIN:~/CAMSERVER$ node -v
v14.17.6

node-fetch package version:节点获取 package 版本:

user@MYLLYTIN:~/CAMSERVER$ npm v node-fetch

node-fetch@3.0.0 | MIT | deps: 2 | versions: 63
A light-weight module that brings Fetch API to node.js
https://github.com/node-fetch/node-fetch

keywords: fetch, http, promise, request, curl, wget, xhr, whatwg

dist
.tarball: https://registry.npmjs.org/node-fetch/-/node-fetch-3.0.0.tgz
.shasum: 79da7146a520036f2c5f644e4a26095f17e411ea
.integrity: sha512-bKMI+C7/T/SPU1lKnbQbwxptpCrG9ashG+VkytmXCPZyuM9jB6VU+hY0oi4lC8LxTtAeWdckNCTa3nrGsAdA3Q==
.unpackedSize: 75.9 kB

dependencies:
data-uri-to-buffer: ^3.0.1 fetch-blob: ^3.1.2         

maintainers:
- endless <jimmy@warting.se>
- bitinn <bitinn@gmail.com>
- timothygu <timothygu99@gmail.com>
- akepinski <npm@kepinski.ch>

dist-tags:
latest: 3.0.0        next: 3.0.0-beta.10  

published 3 days ago by endless <jimmy@warting.se>

esm package version: esm package 版本:

user@MYLLYTIN:~/CAMSERVER$ npm v esm

esm@3.2.25 | MIT | deps: none | versions: 140
Tomorrow's ECMAScript modules today!
https://github.com/standard-things/esm#readme

keywords: commonjs, ecmascript, export, import, modules, node, require

dist
.tarball: https://registry.npmjs.org/esm/-/esm-3.2.25.tgz
.shasum: 342c18c29d56157688ba5ce31f8431fbb795cc10
.integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
.unpackedSize: 308.6 kB

maintainers:
- jdalton <john.david.dalton@gmail.com>

dist-tags:
latest: 3.2.25  

published over a year ago by jdalton <john.david.dalton@gmail.com>

Contents of the.js file (literally nothing but the import): .js 文件的内容(实际上除了导入什么都没有):

user@MYLLYTIN:~/CAMSERVER$ cat server.js 
import fetch from "node-fetch";

Result:结果:

user@MYLLYTIN:~/CAMSERVER$ node -r esm server.js 
/home/user/CAMSERVER/node_modules/node-fetch/src/index.js:1
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/user/CAMSERVER/node_modules/node-fetch/src/index.js
require() of ES modules is not supported.
require() of /home/user/CAMSERVER/node_modules/node-fetch/src/index.js from /home/user/CAMSERVER/server.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 index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/user/CAMSERVER/node_modules/node-fetch/package.json.

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1089:13) {
  code: 'ERR_REQUIRE_ESM'
}
user@MYLLYTIN:~/CAMSERVER$ 

From the Upgrade Guide来自升级指南

node-fetch was converted to be a ESM only package in version 3.0.0-beta.10 . node-fetch 在3.0.0-beta.10版本中被转换为仅 ESM 的包。 node-fetch is an ESM-only module - you are not able to import it with require. node-fetch 是一个仅限 ESM 的模块 - 您无法使用 require 导入它。

Alternatively, you can use the async import() function from CommonJS to load node-fetch asynchronously:或者,您可以使用 CommonJS 中的 async import() 函数来异步加载 node-fetch:

// mod.cjs
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));

or you stay on v2 as they say in the README或者像他们在自述文件中所说的那样继续使用v2

node-fetch is an ESM-only module - you are not able to import it with require. node-fetch是一个仅限 ESM 的模块 - 您无法使用 require 导入它。 We recommend you stay on v2 which is built with CommonJS unless you use ESM yourself.我们建议您继续使用使用 CommonJS 构建的 v2,除非您自己使用 ESM。 We will continue to publish critical bug fixes for it.我们将继续为它发布关键的错误修复。

EDIT编辑

I saw that in the doc, used it, and the script crashes with :我在文档中看到了,使用了它,脚本崩溃了:

error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter.错误 TS2556:展开参数必须具有元组类型或传递给其余参数。

Since you are using typescript you should do something like this由于您使用的是打字稿,因此您应该执行以下操作

import nodeFetch, { RequestInfo, RequestInit } from "node-fetch";

const fetch = (url: RequestInfo, init?: RequestInit) =>  import("node-fetch").then(({ default: fetch }) => nodeFetch(url, init));

I always had errors with previous solutions, this is what worked every single time for me我以前的解决方案总是有错误,这对我来说每次都有效

const _importDynamic = new Function('modulePath', 'return import(modulePath)');

export const fetch = async function (...args: any) {
    const {default: fetch} = await _importDynamic('node-fetch');
    return fetch(...args);
}

node-fetch v3 is ESM-only: https://github.com/node-fetch/node-fetch#loading-and-configuring-the-module . node-fetch v3 仅支持 ESM: https : //github.com/node-fetch/node-fetch#loading-and-configuring-the-module The esm module you're adding is for adding ESM compatibility, but it's unnecessary now that Node 12+ supports ESM natively;您添加的esm模块是为了添加 ESM 兼容性,但现在 Node 12+ 原生支持 ESM 是不必要的; and it doesn't work with ESM-only packages like node-fetch 3+.它不适用于像node-fetch 3+ 这样的仅限 ESM 的软件包。

To fix your issue:要解决您的问题:

  1. Remove the esm package.删除esm包。
  2. Add "type": "module" to your package.json ."type": "module"到您的package.json

And that's it.就是这样。 Then when you run node server.js it should work.然后当你运行node server.js它应该可以工作。

There are a couple of ways to do this:有几种方法可以做到这一点:

  1. specify "type":"module" in package.jsonpackage.json指定"type":"module"
  2. Use this flag --input-type=module when running the file运行文件时使用此标志--input-type=module
  3. use .mjs file extension使用.mjs文件扩展名

Many times that error happens through the current version of fetch what we can do to solve it, is to install a previous version I tried it and it worked for me.很多时候,通过当前版本的 fetch 发生错误,我们可以做些什么来解决它,就是安装我尝试过的以前的版本,它对我有用。

to install the previous version: npm i node-fetch@2.6.1 or whatever you prefer.安装以前的版本: npm i node-fetch@2.6.1或任何你喜欢的。

在此处输入图像描述

I think this link is a comprehensive explanation about Error [ERR_REQUIRE_ESM]: require() of ES [node-fetch Module ] not supported.我认为此链接是关于错误 [ERR_REQUIRE_ESM] 的全面解释:不支持 ES [node-fetch 模块] 的 require()。

node-fetch Error [ERR_REQUIRE_ESM]: require() of ES Module not supported 节点获取错误 [ERR_REQUIRE_ESM]:不支持 ES 模块的 require()

In case someone is solving this issue in 2022:如果有人在 2022 年解决这个问题:

Recent versions of nodejs already includes global fetch api. It is still an experimental feature and may be not ready to be used in production, but if you are writing some basic script or doing some sandbox project, you should definitely try it.最新版本的 nodejs 已经包含了 global fetch api。它仍然是一个实验性的特性,可能还没有准备好在生产中使用,但是如果你正在编写一些基本的脚本或者做一些沙箱项目,你一定要尝试一下。 Works without issues for me.对我来说没有问题。

This is an official announcement and some examples here and here这是一个 官方公告这里这里有一些例子

Since the question was really about requiring node-fetch and there are definitely reasons that a developer might need to use require vs import, the answer to import the module using import() is somewhat accurate but isn't complete, because it ignores the fact that using import is async and if you're using node-fetch in your code in multiple places you're going to have a bit of an async mess all over the place whenever you want to use node-fetch, so the answer is very incomplete IMHO.由于问题实际上是关于要求节点获取,并且开发人员可能需要使用 require 与 import 肯定是有原因的,因此使用 import() 导入模块的答案有些准确但并不完整,因为它忽略了这一事实使用 import 是异步的,如果你在你的代码中的多个地方使用 node-fetch,那么无论何时你想使用 node-fetch,你都会在整个地方有点异步混乱,所以答案是非常不完整恕我直言。 A more complete answer would include a better how-to.更完整的答案将包括更好的操作方法。 Something like the following:类似于以下内容:

You need to use import() rather than require because this is an ES module.您需要使用 import() 而不是 require 因为这是一个 ES 模块。 To avoid an async mess, you'll want to await the importing of this module once and then be able to use it wherever else you need it.为了避免异步混乱,您需要等待此模块的导入一次,然后才能在需要的任何其他地方使用它。 To do that, create a module that imports any of your ES-only modules something like this:为此,请创建一个模块来导入任何 ES-only 模块,如下所示:

"use strict";

let got;
let fetch;

module.exports.load = async function() {
    queueMicrotask(function() {
        // any ESM-only module that needs to be loaded can be loaded here, just add import for each using specific structure of each
        import("got").then(({default: Got}) => got = Got );
        fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
    });

    while(
        // check each module to see if it's been loaded here
        !got || !got.get || !fetch || typeof fetch !== "function"
         ) {
        // waiting for modules to load
        console.log("Waiting for ES-Only modules to load...");
        await new Promise((resolve)=>setTimeout(resolve, 1000));
    }
    module.exports.got = got;
    module.exports.fetch = fetch;
    console.log("ES-Only modules finished loading!");
}

This then allows you to call the await the loading of the ES-Only modules once and then use the module later by grabbing it from your intermediary module like this:然后,这允许您调用一次等待加载 ES-Only 模块,然后稍后通过从中间模块中抓取它来使用该模块,如下所示:

"use strict";

const esmModules = require("esm_modules"); // or whatever you called the intermiary module
async function doMyFetching(url, options) {
   const fetch = esmModules.fetch;
   const result = await fetch(url, options)
}

The nice part of doing it this way is that you know that your ES-Only modules are loaded and you know that once they're loaded you can use them at will throughout the rest of your code in a simple and clean way that doesn't force you to add additional async logic all over the place whenever you need the module.这样做的好处在于,您知道您的 ES-Only 模块已加载,并且您知道一旦加载了它们,您就可以在其余代码中以一种简单而干净的方式随意使用它们,而不是“ t 强制您在需要模块时到处添加额外的异步逻辑。

To fix this, I downgraded node-fetch to the latest version 2, which right now is 2.6.6.为了解决这个问题,我将node-fetch降级到最新版本 2,现在是 2.6.6。 This is the script I ran:这是我运行的脚本:

yarn add node-fetch@^2.6.6

or

npm install node-fetch@^2.6.6

I also added these compiler options:我还添加了这些编译器选项:

{
  "compilerOptions": { "allowJs": true, "outDir": "./dist" },
}

Here is in Typescript, this will install to the global scope, just import the file and fetch ready to use:这里是 Typescript,这将安装到全局 scope,只需导入文件并获取即可使用:

/* filename: fetch.ts */

if (!globalThis.fetch) {
  import('node-fetch').then(({ default: fetch, Headers, Request, Response }) => {
    Object.assign(globalThis, { fetch, Headers, Request, Response })
  })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 不支持 ES 模块的 require() - require() of ES modules not supported Require.js 模块(node-fetch)加载上下文错误 - Require.js module(node-fetch) load for contex error 使用 typescript 在节点项目中导入节点获取 - Importing node-fetch in node project with typescript '不支持 ES 模块的 require()。 ' Node.js、快递、swagger-jsdoc 出错 - 'require() of ES modules is not supported. ' error with Node.js, express, swagger-jsdoc require('node-fetch') 给出 ERR_REQUIRE_ESM - require('node-fetch') gives ERR_REQUIRE_ESM 使用 ES 模块进行条件导入( fetch / node-fetch ) - Conditional import with ES Module ( fetch / node-fetch ) 错误:必须使用 import 加载 ES 模块:不支持 ES 模块的 D:\\node_modules\\react-markdown\\index.js require() - Error: Must use import to load ES Module: D:\node_modules\react-markdown\index.js require() of ES modules is not supported 如果节点获取请求中存在错误,则忽略(或返回) - Ignore (or return) if there is error in node-fetch request 节点获取连接 ETIMEDOUT 错误 - node-fetch connect ETIMEDOUT error 错误 [ERR_REQUIRE_ESM]:不支持来自 /app/commands/Image/meme.js 的 ES 模块 /app/node_modules/got/dist/source/index.js 的 require() - Error [ERR_REQUIRE_ESM]: require() of ES Module /app/node_modules/got/dist/source/index.js from /app/commands/Image/meme.js not supported
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM