できない.dev

Node.js の ESM で「__dirname is not defined」が解決できない

ES Modules では CommonJS の __dirname / __filename が定義されないためです。
import.meta.url から導出するか、Node 20.11 以降なら import.meta.dirname を使います。

公開: 更新:

要約

ReferenceError: __dirname is not defined は、ファイルが ES Modules として実行され、CommonJS のグローバル __dirname / __filename が ESM には存在しないために起きます。import.meta.url から自前で算出するか、Node.js 20.11 以降なら import.meta.dirname を使えば解決します。

よくある原因

  1. ESM で実行されている: package.json"type": "module" がある、または拡張子が .mjs のため、CommonJS のグローバルが無い。
  2. __dirname は CJS 専用: __dirname / __filename / require は CommonJS ラッパーが注入する変数で、ESM スコープには注入されない。
  3. コピペ由来: CommonJS 前提のブログ記事のコードをそのまま ESM プロジェクトに持ち込んでいる。

解決策

1. import.meta.url から導出する(全バージョン対応)

import { fileURLToPath } from "node:url";
import { dirname } from "node:path";
 
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

この手法は Node.js の公式 ESM ドキュメント(新しいタブで開く)で案内されている定番です。

2. import.meta.dirname を使う(Node 20.11+ / 21.2+)

新しめの Node ならワンライナーで済みます。

const dir = import.meta.dirname;   // __dirname 相当
const file = import.meta.filename; // __filename 相当

3. パス結合に使う

import { join } from "node:path";
const configPath = join(import.meta.dirname, "config.json");

import.meta.dirname は Node 20.11.0 / 21.2.0 で追加されたため、それ未満を含むサポート対象がある場合は解決策 1 を採用してください。

実行例

実際に上記の手順を node:20(v20.20.2)環境で動かすと、.mjs ファイルで __dirname を参照した時点で ReferenceError: __dirname is not defined in ES module scope が発生し終了コード 1 となる一方、解決策 1・2 はいずれも終了コード 0 で期待どおりのパスを返す。

== versions ==
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
v20.20.2
Python 3.11.2
git version 2.39.5
 
                                                                               
                This is not the tsc command you are looking for                
                                                                               
 
To get access to the TypeScript compiler, tsc, from the command line either:
 
- Use npm install typescript to first add TypeScript to your project before using npx
- Use yarn to avoid accidentally running code from un-installed packages
v10.5.0
== run ==
--- Node.js バージョン ---
v20.20.2
--- node bad.mjs (ReferenceError: __dirname is not defined を想定)---
file:///tmp/tmp.y3bItGc06P/bad.mjs:1
console.log("__dirname =", __dirname);
                           ^
 
ReferenceError: __dirname is not defined in ES module scope
    at file:///tmp/tmp.y3bItGc06P/bad.mjs:1:28
    at ModuleJob.run (node:internal/modules/esm/module_job:325:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:606:24)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5)
 
Node.js v20.20.2
終了コード: 1
--- 解消1: import.meta.url から導出(全バージョン対応)---
__dirname = /tmp/tmp.y3bItGc06P
終了コード: 0
--- 解消2: import.meta.dirname(Node 20.11+ / 21.2+)---
import.meta.dirname = /tmp/tmp.y3bItGc06P
import.meta.filename = /tmp/tmp.y3bItGc06P/fix2.mjs
終了コード: 0

— 2026-06-21 時点の出力

この記事は役立ちましたか?