"__dirname is not defined in ES module scope": the ESM equivalents you write once and reuse
Problem
Converting a service to "type": "module":
ReferenceError: __dirname is not defined in ES module scope
at file:///app/dist/config/paths.js:5:15
# same root cause, later in the file:
ReferenceError: require is not defined in ES module scopeEvery module that touched paths or lazy-required a config file had the same two reference errors.
Root cause
ESM removed the CJS-era implicit globals: __dirname, __filename, require, and module do not exist in module scope. They were never globals in a strict sense — they were CJS wrapper parameters. The ESM equivalents are explicit, and the migration is small once you know the shapes:
| CJS | ESM | |---|---| | __dirname | path.dirname(fileURLToPath(import.meta.url)) | | __filename | fileURLToPath(import.meta.url) | | require.resolve | createRequire(import.meta.url).resolve(...) | | require (lazy load) | await import(...) or createRequire |
// src/paths.ts
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
… 4 more lines in the fix🔒 the fix — including 5 code blocks — is members-only. $1/mo unlocks everything.