[英]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 的软件包。
要解决您的问题:
esm
包。"type": "module"
到您的package.json
。 就是这样。 然后当你运行node server.js
它应该可以工作。
有几种方法可以做到这一点:
package.json
指定"type":"module"
--input-type=module
.mjs
文件扩展名很多时候,通过当前版本的 fetch 发生错误,我们可以做些什么来解决它,就是安装我尝试过的以前的版本,它对我有用。
安装以前的版本: npm i node-fetch@2.6.1
或任何你喜欢的。
我认为此链接是关于错误 [ERR_REQUIRE_ESM] 的全面解释:不支持 ES [node-fetch 模块] 的 require()。
由于问题实际上是关于要求节点获取,并且开发人员可能需要使用 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.