Using __dirname in ES Modules - import.meta.url Approach

Problem

With "type": "module" in package.json or .mjs files, __dirname and __filename are undefined. You get ReferenceError: __dirname is not defined.

Solution

import { fileURLToPath } from 'url';
import path from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Use as usual
const configPath = path.resolve(__dirname, '../config/settings.json');
const dataDir = path.join(__dirname, '../../data');

Key Points

  • import.meta.url returns the current file’s URL as file:///Users/.... Convert it with fileURLToPath to get a regular path for path.join etc.
  • This is the first issue you hit when migrating from CommonJS to ESM. Two lines at the top of the file, and the rest of your code works as-is.
  • Node.js 20.11+ has built-in import.meta.dirname and import.meta.filename. But the above approach is safer for backward compatibility.