The “__dirname is not defined in ES module scope” error happens in JavaScript when we try to access the __dirname
global variable in an ES module. The __dirname
and __filename
global variables are defined in CommonJS modules, but not in ES modules.
We can fix the “__dirname is not defined in ES module scope” error by using certain functions to create a custom __dirname
variable that works just like the global variable, containing the full path of the file’s current working directly.
index.js
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// C:/cb/cb-js
console.log(__dirname);
// C:\cb\cb-js\index.html
console.log(path.join(__dirname, 'index.html'));
The import.meta
object contains context-specific metadata associated with a certain module, e.g., a module’s file URL.
// file:///C:/cb/cb-js/index.js
console.log(import.meta.url);
So we get the current module’s file URL and pass it to the fileURLToPath
function from the url
module, to convert it to a file path. fileURLToPath
returns a fully-resolved, platform-specific Node.js file path.
// C:\cb\cb-js\index.js
console.log(fileURLToPath('file:///C:/cb/cb-js/index.js'));
After getting the file path, we pass it to the dirname
method from the path
module, to get the full directory path from the file path.
// C:\cb\cb-js
console.log(path.dirname('C:\\cb\\cb-js\\index.js'));
With this, we now have our own __dirname
and __filename
variables.
Here’s the output from logging them from a file on my computer.
__filename
contains the absolute path of the current module file.
__dirname
contains the absolute path of the current module file’s directory.
Create utility for __dirname
and __filename
If we access the __dirname
and __filename
variables frequently, we can abstract the logic for creating them in a utility module and avoid unnecessary repetition.
file-dir-name.js
import { fileURLToPath } from 'url';
import { dirname } from 'path';
export default function fileDirName(meta) {
const __filename = fileURLToPath(meta.url);
const __dirname = dirname(__filename);
return { __dirname, __filename };
}
We’ll be able to use this utility across the various other module files in our project.
index.js
import fileDirName from './file-dir-name.js';
const { __dirname, __filename } = fileDirName(import.meta);
// C:\cb\cb-js
console.log(__dirname);
// C:\cb\cb-js\index.js
console.log(__filename);
Every Crazy Thing JavaScript Does
A captivating guide to the subtle caveats and lesser-known parts of JavaScript.