簡體   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