解决 node-fetch 的 ERR_REQUIRE_ESM 错误
问题描述
当在 Node.js 项目中尝试使用 CommonJS 的 require()
语法导入 node-fetch
时,可能会遇到以下错误:
const fetch = require('node-fetch');
错误信息:
Error [ERR_REQUIRE_ESM]: require() of ES Module not supported.
Instead change the require to a dynamic import() which is available in all CommonJS modules.
这是因为从 node-fetch
v3.0.0 开始,该包已转为仅支持 ES 模块(ESM)格式,不再支持传统的 CommonJS 格式的 require()
导入方式。
解决方案
方案一:降级到 node-fetch v2(推荐方案)
最直接的解决方法是降级到仍然支持 CommonJS 的 v2 版本:
# 卸载当前版本
npm uninstall node-fetch
# 安装 v2 版本
npm install node-fetch@2
安装完成后,您可以继续使用传统的 require()
语法:
const fetch = require('node-fetch');
TIP
v2 版本仍然会收到关键错误修复,适合需要保持 CommonJS 模块系统的项目。
方案二:使用动态导入
Node.js 支持在 CommonJS 模块中使用动态 import()
语法:
// 使用动态导入包装 node-fetch
const fetch = (...args) =>
import('node-fetch').then(({default: fetch}) => fetch(...args));
这种方法允许您在保持 CommonJS 代码结构的同时,使用 ESM 包。
方案三:使用 Node.js 18+ 的内置 fetch
如果您使用的是 Node.js 18.0.0 或更高版本,可以考虑直接使用全局的 fetch
API:
// Node.js 18+ 原生支持 fetch
const res = await fetch('https://api.example.com/data');
if (res.ok) {
const data = await res.json();
console.log(data);
}
INFO
Node.js 18 中的 fetch
目前仍处于实验阶段,可以通过 --no-experimental-fetch
标志禁用。
方案四:使用兼容替代包
cross-fetch
cross-fetch
是一个跨环境的 fetch 实现,支持 CommonJS 和 ES 模块:
npm install cross-fetch
const fetch = require('cross-fetch');
node-fetch-commonjs
这是一个专门为 CommonJS 环境封装的 node-fetch
版本:
npm install node-fetch-commonjs
const fetch = require('node-fetch-commonjs');
方案五:创建自定义包装器
您可以创建一个自定义的包装模块来处理 ESM 导入:
fetch.js:
exports.fetch = async function (url, init) {
const {default: fetch} = await import("node-fetch");
return await fetch(url, init);
};
使用方式:
const {fetch} = require("./fetch");
// 然后正常使用 fetch
const response = await fetch('https://api.example.com');
总结
解决方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
降级到 v2 | 需要快速修复 | 简单直接,兼容性好 | 不是最新版本 |
动态导入 | 想用 v3 但需保持 CommonJS | 无需降级 | 语法稍复杂 |
Node.js 内置 fetch | 使用 Node.js 18+ | 无需额外依赖 | 实验性功能 |
替代包 (cross-fetch) | 需要跨环境兼容 | 良好的兼容性 | 基于 node-fetch v2 |
自定义包装器 | 需要精确控制 | 高度可定制 | 需要额外代码 |
WARNING
如果您使用 TypeScript,请注意动态导入可能需要额外的类型声明文件来获得完整的类型支持。
选择最适合您项目需求的解决方案。对于大多数情况,降级到 node-fetch@2
或使用 cross-fetch
是最简单可靠的方法。如果您正在启动新项目且使用 Node.js 18+,考虑直接使用内置的 fetch
API。