Node.js でのモジュール判定(.mjs / .cjs / package.json)

Node.js では ES Modules と CommonJS の両方をサポートしています。どちらのモジュールシステムとして扱われるかは、ファイル拡張子や package.json の設定によって決まります。

ファイル拡張子による判定

拡張子モジュールシステム
.mjs常に ES Modules
.cjs常に CommonJS
.jspackage.json の type による
// utils.mjs - 常に ES Modules
export function helper() {
  return 'ESM';
}
// utils.cjs - 常に CommonJS
module.exports = {
  helper: function() {
    return 'CJS';
  }
};

package.json の type フィールド

.js ファイルのデフォルトの扱いを設定します。

{
  "name": "my-project",
  "type": "module"
}
"type": "module"

.js ファイルは ES Modules として扱われる

"type": "commonjs"(デフォルト)

.js ファイルは CommonJS として扱われる

判定の優先順位

ファイル拡張子を確認(.mjs / .cjs)

拡張子が .js なら、最も近い package.json の type を確認

type がなければ CommonJS として扱う

実践的なプロジェクト構成

my-project/
├── package.json       # "type": "module"
├── src/
│   ├── index.js      # ES Modules として扱われる
│   └── utils.js      # ES Modules として扱われる
├── scripts/
│   └── build.cjs     # CommonJS(.cjs で明示)
└── config/
    └── legacy.cjs    # CommonJS(.cjs で明示)
{
  "name": "my-project",
  "type": "module",
  "scripts": {
    "build": "node scripts/build.cjs"
  }
}

サブディレクトリの package.json

サブディレクトリに package.json を置くことで、そのディレクトリ以下の .js ファイルの扱いを変更できます。

my-project/
├── package.json        # "type": "module"
├── src/
│   └── index.js       # ES Modules
└── legacy/
    ├── package.json   # "type": "commonjs"
    └── old-code.js    # CommonJS
// legacy/package.json
{
  "type": "commonjs"
}

相互運用

ES Modules から CommonJS を読み込むことができます。

// ESM から CJS を読み込む
import cjsModule from './lib.cjs';
import cjsPackage from 'some-cjs-package';

// default として全体がインポートされる
console.log(cjsModule);

CommonJS から ES Modules を読み込むには、動的 import() を使用します。

// CJS から ESM を読み込む(非同期)
async function main() {
  const esmModule = await import('./lib.mjs');
  console.log(esmModule.default);
}

main();
注意点

CommonJS から ES Modules を require() で読み込むことはできません。必ず import() を使用してください。

Node.js バージョンによる違い

Node.js 12:ES Modules は実験的サポート(フラグが必要)
Node.js 14+:ES Modules が安定版として利用可能
Node.js 20+:さらに多くの ESM 機能がサポート

確認方法

現在のモジュールタイプを確認するには、以下のように判定できます。

// ES Modules かどうかを確認
if (typeof import.meta !== 'undefined') {
  console.log('ES Modules');
} else {
  console.log('CommonJS');
}

ファイル拡張子と package.json を適切に設定することで、プロジェクト内で ES Modules と CommonJS を共存させることができます。