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

vvppvyoh  于 2022-12-03  发布在  Node.js
关注(0)|答案(9)|浏览(791)

我正在创建一个程序来分析监控摄像头流,但在第一行就卡住了。目前,我的.js文件除了节点获取的导入外什么都没有,它给了我一个错误消息。我做错了什么?
在Linux的Windows子系统中运行Ubuntu 20.04.2 LTS。
节点版本:

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

节点提取包版本:

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软件包版本:

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$
ibps3vxo

ibps3vxo1#

Upgrade Guide
在版本3.0.0-beta.10中,node-fetch已转换为仅限ESM的软件包。node-fetch是仅限ESM的模块-无法使用require导入它。
或者,可以使用CommonJS中的async import()函数异步加载节点获取:

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

或者你就像README里说的那样
node-fetch是一个仅支持ESM模块-您不能使用require导入它。我们建议您继续使用v2,它是使用CommonJS构建的,除非您自己使用ESM。我们将继续发布它的关键错误修复程序。

编辑

我在文档中看到了这一点,使用了它,脚本崩溃了:
错误TS 2556:spread参数必须具有Tuple类型或传递给rest参数。
既然你使用的是 typescript ,你应该这样做

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

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

nnt7mjpx2#

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

yarn add node-fetch@^2.6.6

npm install node-fetch@^2.6.6

我还添加了以下编译器选项:

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

jckbn6z73#

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软件包。
1.将"type": "module"添加到您的package.json
就是这样,当你运行node server.js的时候,它应该可以工作。

osh3o9ms

osh3o9ms4#

我以前的解决方案总是有错误,这是对我来说每一次都有效的方法
npm i -D node-fetch

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);
}
13z8s7eq

13z8s7eq5#

使用ESM语法,也可以在运行文件之前使用以下方法之一。
1.在package.json中指定"type":"module"
1.或者在运行文件时使用此标志--input-type=module
1.或使用.mjs文件扩展名

r9f1avp5

r9f1avp56#

很多时候,错误发生通过当前版本的获取我们可以做什么来解决它,是安装以前的版本我尝试了它,它为我工作.
安装先前版本:npm i node-fetch@2.6.1或任何你喜欢的。

gev0vcfq

gev0vcfq7#

由于这个问题实际上是关于需要节点获取的,并且开发人员可能需要使用require与import的原因是明确的,所以使用import来导入模块的答案是()在一定程度上准确但不完整,因为它忽略了这样一个事实,即使用import是异步的,并且如果您在代码中的多个位置使用节点获取,每当你想使用node-fetch的时候,你就会有一点异步混乱,所以答案是非常不完整的。一个更完整的答案应该包括一个更好的方法。如下所示:
你需要使用import()而不是require,因为这是一个ES模块。为了避免异步混乱,你需要等待一次这个模块的导入,然后就可以在任何需要它的地方使用它了。为此,创建一个模块来导入任何ES专用模块,如下所示:

"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!");
}

这样,您就可以调用wait the loading of the 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专用模块,而且一旦加载了这些模块,您就可以在代码的其余部分中以一种简单、干净的方式随意使用它们,而不必在需要模块时到处添加额外的异步逻辑。

tzdcorbm

tzdcorbm8#

这里是在Typescript中,这将安装到全局范围,只需导入文件并提取即可用途:

/* filename: fetch.ts */

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

lx0bsm1f9#

我认为此链接是关于***Error [ERR_REQUIRE_ESM]的全面说明:不支持ES [节点获取模块]的require()。***
node-fetch Error [ERR_REQUIRE_ESM]: require() of ES Module not supported

相关问题