Skip to content

解决 node-fetch ES 模块导入错误

问题描述

当在 Node.js 项目中尝试导入 node-fetch 时,开发者可能会遇到以下错误:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
require() of ES modules is not supported.

这个错误表示你正在尝试使用 require() 语法来导入一个仅支持 ES 模块 (ESM) 的包。从 node-fetch v3.0.0 开始,该包已转为纯 ESM 模块,不再支持 CommonJS 的 require() 导入方式。

解决方案

方案一:使用 Node.js 内置 fetch(推荐)

从 Node.js v18.0.0 开始,fetch API 已成为全局内置功能,无需额外安装:

javascript
// 直接使用全局 fetch
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);

TIP

Node.js v18+ 内置的 fetch 处于实验阶段,但对于大多数用例已经足够稳定。

方案二:降级 node-fetch 版本

如果必须使用 node-fetch 且不想迁移到 ESM,可以降级到 v2 版本:

bash
# 使用 npm
npm install node-fetch@2.6.6

# 使用 yarn
yarn add node-fetch@^2.6.6

降级后可以使用 CommonJS 语法:

javascript
const fetch = require('node-fetch');

方案三:迁移到 ES 模块

将你的项目转换为 ES 模块项目:

  1. package.json 中添加:
json
{
  "type": "module"
}
  1. 使用 ES 模块导入语法:
javascript
import fetch from 'node-fetch';

方案四:使用动态导入

对于 CommonJS 项目,可以使用动态导入:

javascript
// 方法一:简单封装
const fetch = (...args) => 
  import('node-fetch').then(({ default: fetch }) => fetch(...args));

// 方法二:TypeScript 友好版本
import { RequestInfo, RequestInit, Response } from 'node-fetch';

const nodeFetch = async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
  const { default: fetch } = await import('node-fetch');
  return fetch(url, init);
};

方案五:使用替代库

考虑使用其他兼容 CommonJS 的 HTTP 请求库:

bash
# axios
npm install axios

# got
npm install got

# gaxios (Google的轻量级替代品)
npm install gaxios

使用示例(gaxios):

javascript
const { request } = require('gaxios');

const result = await request({
  url: 'https://api.example.com/data',
  responseType: 'json'
});

最佳实践建议

  1. 优先使用 Node.js 内置 fetch(如果使用 Node.js v18+)
  2. 新项目直接使用 ES 模块,在 package.json 中设置 "type": "module"
  3. 现有 CommonJS 项目考虑使用动态导入或降级 node-fetch
  4. TypeScript 项目可以使用 tsx 工具无缝运行 TypeScript 和 ESM
bash
# 使用 tsx 运行 TypeScript
npx tsx server.ts

总结

node-fetch v3+ 仅支持 ES 模块是导致此错误的主要原因。根据你的项目需求和 Node.js 版本,可以选择使用内置 fetch、降级 node-fetch、迁移到 ESM 或使用动态导入等解决方案。对于新项目,建议直接使用 Node.js v18+ 的内置 fetch API,既无需额外依赖,又能获得最佳性能。

WARNING

无论选择哪种方案,都建议测试相关功能以确保兼容性和稳定性,特别是在生产环境中。