Skip to content

node-fetchでERR_REQUIRE_ESMエラーが発生する原因と解決方法

問題の概要

Node.jsプロジェクトでnode-fetchを使用する際、以下のコードを実行するとエラーが発生します:

javascript
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のバージョン3以降がES Modules (ESM) のみのパッケージとなったために発生します。

なぜこのエラーが発生するのか

Node.jsは2種類のモジュールシステムをサポートしています:

  • CommonJS: require()module.exports を使用
  • ES Modules (ESM): importexport を使用

node-fetchのバージョン3.0.0以降はESMのみで提供されるようになり、CommonJSのrequire()では読み込めなくなったためこのエラーが発生します。

解決方法

方法1: node-fetchのバージョン2を継続使用

最も簡単な解決策は、CommonJS互換のバージョン2を使用することです:

bash
npm uninstall node-fetch
npm install node-fetch@2

TIP

バージョン2も重要なバグ修正は継続して提供されるため、安定性を求める場合はこの方法がおすすめです。

方法2: 動的インポートを使用

CommonJS環境でESMモジュールを使用するには、動的インポートを活用します:

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

このワンライナーにより、非同期でnode-fetchを読み込むことができます。

方法3: ラッパーモジュールの作成

頻繁に使用する場合は、ラッパーファイルを作成する方法もあります:

fetch.js:

javascript
exports.fetch = async function (url, init) {
    const { default: fetch } = await import("node-fetch");
    return await fetch(url, init);
};

使用例:

javascript
const { fetch } = require("./fetch");

// 通常通り使用可能
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));

方法4: 代替パッケージの使用

cross-fetch

CommonJSとESMの両方をサポートする互換パッケージ:

bash
npm install cross-fetch
javascript
const fetch = require('cross-fetch');

WARNING

cross-fetchは現時点でnode-fetchのバージョン2をラップしているため、最新の機能は利用できません。

node-fetch-commonjs

CommonJS用に特別に設計されたバージョン:

bash
npm install node-fetch-commonjs
javascript
const fetch = require('node-fetch-commonjs');

方法5: Node.js組み込みのfetch機能を使用

最新情報

Node.js 18.0.0以降では、実験的な機能としてグローバルなfetch APIが組み込まれています

javascript
// Node.js 18+ では組み込みのfetchが使用可能
const res = await fetch('https://api.example.com/data');
if (res.ok) {
  const data = await res.json();
  console.log(data);
}

この機能はfetchFormDataHeadersRequestResponseなどのグローバルオブジェクトを提供します。

実験的機能について

組み込みfetchはまだ実験的な機能のため、本番環境で使用する場合は--no-experimental-fetchフラグで無効化されていないか確認してください。

まとめ

解決方法適用場景メリットデメリット
バージョン2使用安定性重視簡単、互換性問題なし最新機能が使えない
動的インポート最新版を使用したい最新機能が使える非同期処理が必要
代替パッケージ互換性重視簡単に導入可能パフォーマンスや機能面での制限
Node.js組み込み機能Node.js 18+ユーザー追加パッケージ不要実験的機能である

プロジェクトの状況に応じて最適な解決方法を選択してください。特に、Node.js 18以降を使用している場合は、組み込みのfetch機能の利用を検討することをおすすめします。