How to Update __dirname in Node.js for ES Modules
Note: This post has been updated to reflect the latest changes in Node.js regarding
__dirname
and ES modules. See references: Node.js ESM docs, SonarSource blog.
__dirname is back in Node.js with ES modules
ECMAScript modules (ES modules) are now the standard for packaging JavaScript code. Node.js has moved from CommonJS to ES modules, and one major friction point—accessing the current module's directory—has finally been resolved.
TL;DR
In modern Node.js (v20.11.0+), you can use:
import.meta.dirname
import.meta.filename
See: Node.js ESM docs
Evolution: CommonJS to ES Modules
The old CommonJS way
__dirname // The current module's directory name
__filename // The current module's file name
The old ES module workaround
Previously, ES modules did not have __dirname
or __filename
. You had to use:
import * as url from 'url';
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const __filename = url.fileURLToPath(import.meta.url);
The new ES module way (Node.js v20.11.0+)
Now, you can simply use:
const __dirname = import.meta.dirname;
const __filename = import.meta.filename;
This removes the need for boilerplate and is the recommended approach for all new Node.js projects using ES modules.
Using URLs and Paths in Node.js ES Modules
Node.js APIs that accept file paths also accept URL
objects. For example, to read a file relative to your module:
import { join } from 'node:path';
import { readFile } from 'node:fs/promises';
// Using import.meta.dirname (Node.js v20.11.0+)
const filePath = join(import.meta.dirname, 'data.json');
const data = await readFile(filePath, { encoding: 'utf8' });
// Or, using URL objects (works in all ES modules)
const fileUrl = new URL('data.json', import.meta.url);
const data2 = await readFile(fileUrl, { encoding: 'utf8' });
Using URL
objects is especially useful for code that may run in both Node.js and browser environments, as it provides consistency.
Browser and REPL Caveats
import.meta.dirname
andimport.meta.filename
are only available when the module is loaded from the file system (i.e.,import.meta.url
starts withfile:
). In browsers, these will beundefined
.- The Node.js REPL does not support
import.meta
properties as of Node.js v21.x (StackOverflow).