ESMで__dirnameを使う - import.meta.urlの活用法
問題
package.jsonに"type": "module"を設定するか.mjsファイルを使うと、__dirnameと__filenameが定義されません。ReferenceError: __dirname is not definedエラーが発生します。
解決方法
import { fileURLToPath } from 'url';
import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 従来通り使用可能
const configPath = path.resolve(__dirname, '../config/settings.json');
const dataDir = path.join(__dirname, '../../data');
ポイント
import.meta.urlは現在のファイルのURLをfile:///Users/...形式で返します。fileURLToPathで通常のファイルパスに変換しないと、path.joinなどで使えません。- CommonJS(
require)からESMへの移行時に最初にぶつかるのがこの問題です。ファイル上部にこの2行を追加するだけで、残りのコードはそのまま使えます。 - Node.js 20.11以降では
import.meta.dirnameとimport.meta.filenameが内蔵されています。ただし、下位互換性のためには上記の方法が安全です。