Today I needed to update the __dirname
variable in Node.js for ES modules. The sqlite-vss
package I was using was throwing an error when I tried to import it into my project, so I needed to switch to using ES modules.
$ node
Welcome to Node.js v18.16.0.
Type ".help" for more information.
> const sqlite_vss = require('sqlite-vss')
Uncaught:
Error [ERR_REQUIRE_ESM]: require() of ES Module ./node_modules/sqlite-vss/src/index.js not supported. Instead change the require of index.js in null to a dynamic import() which is available in all CommonJS modules.
The first step was to add {"type": "module"}
in my package.json
file.
To get __dirname
back, I defined a constant that resolves to the inbuilt globals that were provided to CommonJS code using the url
module and import.meta
. The code below works since a new, standardized global called import.meta.url
is provided by ESM.
import { fileURLToPath } from 'url'
const __dirname = fileURLToPath(new URL('.', import.meta.url))
From there, it's possible to use path.join()
like you would normally
import { join } from 'path'
const filePath = join(__dirname, 'test.js')
When using Node.js >= 20.11, we no longer need to define __dirname
. A dirname property is available on import.meta
.
const __dirname = import.meta.dirname
For now, the import.meta
is still not available in the Node.js REPL. The REPL will throw an error:
$ node
Welcome to Node.js v21.7.2.
Type ".help" for more information.
> import.meta.dirname
import.meta.dirname
^^^^
Uncaught SyntaxError:
Cannot use 'import.meta' outside a module