
問題・背景|ReferenceError: __dirname is not defined in ES module scope
Node.jsで__dirname
を使用すると、現在のJavaScriptファイルが存在するフォルダーのパスを取得できる。
Node.jsを扱っている者なら、利用することが多い機能の1つだと思う。
がしかし、__dirname
はCommon JSでしかサポートされておらず、ES Moduleで利用しようとすると怒られてしまう。
ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/example/example/example/example/server/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.約)
__dirname
はES moduleスコープでは定義されていません。package.jsonで"type":"module"
を指定していてかつ拡張子が.js
なので、このファイルはES moduleとして扱われます。CommonJSのScript(__dirname
のこと)を利用したい場合は、拡張子に.cjs
を使用してください。
ちなみにこのエラーは次のコードを記述した際に発生した。
app.use(express.static(path.join(__dirname, '../client/build')));
この場合、素直に拡張子に.cjs
を使用するなりpackage.jsonで"type":"commonjs"
を記述するなりして、Common JSファイルとして取り扱えば済むのだが、どうしてもES Moduleを利用したいシーンもあるだろう。
解決策
結論として、この問題は{fileURLToPath}
モジュールを利用することで解決できる。
まずは、Node.js側(index.jsファイル)にて、path
とfileURLToPath
をimportする。
import path from 'path';
import { fileURLToPath } from 'url';
次に、fileURLToPath
を利用して、__dirname
の機能を疑似的に再現する。
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
これで、ES ModuleでもCommonJSの__dirname機能を再現できる。
How to fix "__dirname is not defined in ES module scope"