Skip to content

package.jsonのtype: moduleについて

問題の概要

Node.jsプロジェクトでpackage.json"type": "module"を設定すると、以下のようなエラーが発生することがあります:

bash
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標準のモジュールシステム(importexportを使用)
json
// package.json
{
  "type": "module", // .jsファイルをES Modulesとして扱う
  // または省略(デフォルトはCommonJS)
}

設定による挙動の違い

設定.jsファイルの扱い使用する構文
"type": "module"ES Modulesimport, export
"type": "commonjs" または未設定CommonJSrequire(), module.exports

解決策

方法1: モジュールタイプの一貫性を保つ

プロジェクト全体で一貫したモジュールシステムを使用することが推奨されます。

ES Modulesを使用する場合:

json
// package.json
{
  "type": "module",
  "scripts": {
    "start": "node index.js"
  }
}
javascript
// index.js (ES Modules構文を使用)
import express from 'express';
// ES Modulesの構文でコードを書く

CommonJSを使用する場合:

json
// package.json
{
  "type": "commonjs",
  // またはtypeフィールドを省略
}
javascript
// index.js (CommonJS構文を使用)
const express = require('express');
// CommonJSの構文でコードを書く

方法2: ファイル拡張子を使い分ける

混合環境では、ファイル拡張子でモジュールタイプを明示できます。

javascript
// .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以降では、実験的な機能としてモジュールタイプの自動検出が利用できます。

bash
# モジュールタイプを自動検出
node --experimental-detect-module index.js

# デフォルトのモジュールタイプを変更
node --experimental-default-type="module" index.js

package.jsonのscriptsで設定することも可能です:

json
{
  "scripts": {
    "start": "node --experimental-detect-module index.js",
    "dev": "node --experimental-default-type=\"module\" index.js"
  }
}

方法4: 入力タイプの指定

CI/CD環境などで一時的にES Modulesを使用する場合:

bash
# package.jsonのtype設定に関わらずES Modulesとして実行
echo "import { myFunc } from 'myModule';" | node --input-type=module

注意点

互換性の問題

既存のCommonJSプロジェクトに"type": "module"を追加すると、すべてのrequire()呼び出しでエラーが発生します。段階的な移行が必要です。

推奨アプローチ

  1. 新しいプロジェクトでは"type": "module"を使用してES Modulesを採用する
  2. 既存のプロジェクトは徐々に移行するか、拡張子を使い分ける
  3. ライブラリ開発者は両方のモジュールシステムをサポートすることを検討する

まとめ

"type": "module"はNode.jsの重要な設定であり、プロジェクトのモジュールシステムを決定します。エラーが発生した場合は、プロジェクトの要件に合わせて適切な解決策を選択してください。最新のNode.jsバージョンでは、より柔軟なオプションが利用できるようになっています。