【问题标题】:Error: require() of ES modules is not supported when importing node-fetch错误:导入 node-fetch 时不支持 ES 模块的 require()
【发布时间】:2021-11-01 14:10:23
【问题描述】:

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

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

节点版本:

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

node-fetch 包版本:

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$ 

【问题讨论】:

  • 它们是 nodejs 的两种模块语法。 commonJS 语法,使用 requiremodule.exports,以及 ES 语法,使用 import * from "path" 模块样式。默认情况下,nodejs 将尝试使用 CommonJS 语法加载模块。如果要使用 ES 语法,则必须在 package.json 中指定 "type":"module"。但是你不能把它们混在一起。您可以使用一种语法,但不能同时使用两种语法。
  • @Ariart 我在我的代码中使用 ES 语法,并且 node-fetch 确实有 "type": module in it's package.json
  • 是否在你的项目package.json中指定?
  • @Ariart 我什至没有 package.json,创建了一个只包含 "type": "module" 的 package.json 并且有效!谢谢!有没有办法在运行节点时设置这个内联而不是在 package.json 中定义它?
  • 是的,您可以运行带有标志的节点。根据记忆,它类似于--input-type=module

标签: javascript node.js node-fetch


【解决方案1】:

来自Upgrade Guide

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

或者,您可以使用 CommonJS 中的 async import() 函数来异步加载节点获取:

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

或者您继续使用 v2,正如他们在 README 中所说的那样

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));

【讨论】:

  • 我在文档中看到,使用它,脚本崩溃:error TS2556: A spread argument must either have a tuple type or be passed to a rest parameter. Node.js 14.17.1
  • @JeremyTille 我已经更新了我的答案。我还没有测试过,所以请告诉我它是否有效。
  • 非常感谢。我试过了,但我得到了Error [ERR_REQUIRE_ESM]: Must use import to load ES Module. require() of ES modules is not supported. index.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 node_modules/node-fetch/package.json. 它一直说我正在使用require,但我正在使用import。使用 ts-node-dev index.ts 运行我的 TS 文件。
  • @JeremyThille 你知道为什么吗?我和你一样 - 我已经在使用 import。
  • 由于“import nodeFetch...”语句,它不起作用。您应该只导入类型而不是实现。这应该工作:import { RequestInfo, RequestInit } from 'node-fetch'; const fetch = (url: RequestInfo, init?: RequestInit) =&gt; import('node-fetch').then(({ default: fetch }) =&gt; fetch(url, init));
【解决方案2】:

node-fetch v3 仅适用于 ESM:https://github.com/node-fetch/node-fetch#loading-and-configuring-the-module。您添加的 esm 模块用于添加 ESM 兼容性,但现在 Node 12+ 原生支持 ESM 就没有必要了;它不适用于仅 ESM 的软件包,例如 node-fetch 3+。

解决您的问题:

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

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

【讨论】:

【解决方案3】:

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

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

【讨论】:

    猜你喜欢
    • 2022-11-18
    • 2022-11-09
    • 1970-01-01
    • 2022-12-09
    • 2021-12-28
    • 2021-11-03
    • 1970-01-01
    • 2021-06-05
    • 2021-10-30
    相关资源
    最近更新 更多