繁体   English   中英

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

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

我正在创建一个程序来分析安全摄像头流并卡在第一行。 目前 my.js 文件只有 node-fetch 的导入,它给了我一条错误消息。 我究竟做错了什么?

在 Linux 的 Windows 子系统中运行 Ubuntu 20.04.2 LTS。

节点版本:

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

节点获取 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 版本:

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>

.js 文件的内容(实际上除了导入什么都没有):

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

结果:

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$ 

来自升级指南

node-fetch 在3.0.0-beta.10版本中被转换为仅 ESM 的包。 node-fetch 是一个仅限 ESM 的模块 - 您无法使用 require 导入它。

或者,您可以使用 CommonJS 中的 async import() 函数来异步加载 node-fetch:

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

或者像他们在自述文件中所说的那样继续使用v2

node-fetch是一个仅限 ESM 的模块 - 您无法使用 require 导入它。 我们建议您继续使用使用 CommonJS 构建的 v2,除非您自己使用 ESM。 我们将继续为它发布关键的错误修复。

编辑

我在文档中看到了,使用了它,脚本崩溃了:

错误 TS2556:展开参数必须具有元组类型或传递给其余参数。

由于您使用的是打字稿,因此您应该执行以下操作

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

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

我以前的解决方案总是有错误,这对我来说每次都有效

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 仅支持 ESM: https : //github.com/node-fetch/node-fetch#loading-and-configuring-the-module 您添加的esm模块是为了添加 ESM 兼容性,但现在 Node 12+ 原生支持 ESM 是不必要的; 它不适用于像node-fetch 3+ 这样的仅限 ESM 的软件包。

要解决您的问题:

  1. 删除esm包。
  2. "type": "module"到您的package.json

就是这样。 然后当你运行node server.js它应该可以工作。

有几种方法可以做到这一点:

  1. package.json指定"type":"module"
  2. 运行文件时使用此标志--input-type=module
  3. 使用.mjs文件扩展名

很多时候,通过当前版本的 fetch 发生错误,我们可以做些什么来解决它,就是安装我尝试过的以前的版本,它对我有用。

安装以前的版本: npm i node-fetch@2.6.1或任何你喜欢的。

在此处输入图像描述

我认为此链接是关于错误 [ERR_REQUIRE_ESM] 的全面解释:不支持 ES [node-fetch 模块] 的 require()。

节点获取错误 [ERR_REQUIRE_ESM]:不支持 ES 模块的 require()

如果有人在 2022 年解决这个问题:

最新版本的 nodejs 已经包含了 global fetch api。它仍然是一个实验性的特性,可能还没有准备好在生产中使用,但是如果你正在编写一些基本的脚本或者做一些沙箱项目,你一定要尝试一下。 对我来说没有问题。

这是一个 官方公告这里这里有一些例子

由于问题实际上是关于要求节点获取,并且开发人员可能需要使用 require 与 import 肯定是有原因的,因此使用 import() 导入模块的答案有些准确但并不完整,因为它忽略了这一事实使用 import 是异步的,如果你在你的代码中的多个地方使用 node-fetch,那么无论何时你想使用 node-fetch,你都会在整个地方有点异步混乱,所以答案是非常不完整恕我直言。 更完整的答案将包括更好的操作方法。 类似于以下内容:

您需要使用 import() 而不是 require 因为这是一个 ES 模块。 为了避免异步混乱,您需要等待此模块的导入一次,然后才能在需要的任何其他地方使用它。 为此,请创建一个模块来导入任何 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!");
}

然后,这允许您调用一次等待加载 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)
}

这样做的好处在于,您知道您的 ES-Only 模块已加载,并且您知道一旦加载了它们,您就可以在其余代码中以一种简单而干净的方式随意使用它们,而不是“ t 强制您在需要模块时到处添加额外的异步逻辑。

为了解决这个问题,我将node-fetch降级到最新版本 2,现在是 2.6.6。 这是我运行的脚本:

yarn add node-fetch@^2.6.6

or

npm install node-fetch@^2.6.6

我还添加了这些编译器选项:

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

这里是 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM