package.jsonのtype: moduleについて
問題の概要
Node.jsプロジェクトでpackage.json
に"type": "module"
を設定すると、以下のようなエラーが発生することがあります:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module:
~~/nuxt.config.js
require() of ES modules is not supported.
require() of ~~/nuxt.config.js from
~~/config.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 nuxt.config.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from ~~/package.json.
このエラーは、モジュールシステムの互換性の問題によって発生します。
type: moduleの役割
"type": "module"
は、Node.jsが.js
ファイルをどのように解釈するかを決定する設定です。
Node.jsのモジュールシステム
- CommonJS: 従来のNode.jsのモジュールシステム(
require()
とmodule.exports
を使用) - ES Modules: ECMAScript標準のモジュールシステム(
import
とexport
を使用)
// package.json
{
"type": "module", // .jsファイルをES Modulesとして扱う
// または省略(デフォルトはCommonJS)
}
設定による挙動の違い
設定 | .jsファイルの扱い | 使用する構文 |
---|---|---|
"type": "module" | ES Modules | import , export |
"type": "commonjs" または未設定 | CommonJS | require() , module.exports |
解決策
方法1: モジュールタイプの一貫性を保つ
プロジェクト全体で一貫したモジュールシステムを使用することが推奨されます。
ES Modulesを使用する場合:
// package.json
{
"type": "module",
"scripts": {
"start": "node index.js"
}
}
// index.js (ES Modules構文を使用)
import express from 'express';
// ES Modulesの構文でコードを書く
CommonJSを使用する場合:
// package.json
{
"type": "commonjs",
// またはtypeフィールドを省略
}
// index.js (CommonJS構文を使用)
const express = require('express');
// CommonJSの構文でコードを書く
方法2: ファイル拡張子を使い分ける
混合環境では、ファイル拡張子でモジュールタイプを明示できます。
// .mjsファイルは常にES Modulesとして扱われる
import { functionA } from './module.mjs';
// .cjsファイルは常にCommonJSとして扱われる
const functionB = require('./module.cjs');
方法3: Node.jsの新しい機能を利用する(v20.10.0以降)
Node.js v20.10.0以降では、実験的な機能としてモジュールタイプの自動検出が利用できます。
# モジュールタイプを自動検出
node --experimental-detect-module index.js
# デフォルトのモジュールタイプを変更
node --experimental-default-type="module" index.js
package.jsonのscriptsで設定することも可能です:
{
"scripts": {
"start": "node --experimental-detect-module index.js",
"dev": "node --experimental-default-type=\"module\" index.js"
}
}
方法4: 入力タイプの指定
CI/CD環境などで一時的にES Modulesを使用する場合:
# package.jsonのtype設定に関わらずES Modulesとして実行
echo "import { myFunc } from 'myModule';" | node --input-type=module
注意点
互換性の問題
既存のCommonJSプロジェクトに"type": "module"
を追加すると、すべてのrequire()
呼び出しでエラーが発生します。段階的な移行が必要です。
推奨アプローチ
- 新しいプロジェクトでは
"type": "module"
を使用してES Modulesを採用する - 既存のプロジェクトは徐々に移行するか、拡張子を使い分ける
- ライブラリ開発者は両方のモジュールシステムをサポートすることを検討する
まとめ
"type": "module"
はNode.jsの重要な設定であり、プロジェクトのモジュールシステムを決定します。エラーが発生した場合は、プロジェクトの要件に合わせて適切な解決策を選択してください。最新のNode.jsバージョンでは、より柔軟なオプションが利用できるようになっています。