I use the flag --experimental-modules
when running my node application in order to use ES6 modules.
However when I use this flag the metavariable
I use this option, since the path starts with file://
just remove that part.
const __filename = import.meta.url.slice(7);
const __dirname = import.meta.url.slice(7, import.meta.url.lastIndexOf("/"));
For Node 10.12 +...
Assuming you are working from a module, this solution should work, and also gives you __filename support as well
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
The nice thing is that you are also only two lines of code away from supporting require() for CommonJS modules. For that you would add:
import { createRequireFromPath } from 'module';
const require = createRequireFromPath(__filename);
I used:
import path from 'path';
const __dirname = path.resolve(path.dirname(decodeURI(new URL(import.meta.url).pathname)));
decodeURI
was important: used spaces and other stuff within the path on my test system.
path.resolve()
handles relative urls.
edit:
fix to support windows (/C:/...
=> C:/...
):
import path from 'path';
const __dirname = (() => {let x = path.dirname(decodeURI(new URL(import.meta.url).pathname)); return path.resolve( (process.platform == "win32") ? x.substr(1) : x ); })();
I made this module es-dirname that will return the current script dirname.
import dirname from 'es-dirname'
console.log(dirname())
It works both in CommonJs scripts and in ES Modules both on Windows and Linux.
Open an issue there if have an error as the script has been working so far in my projects but it might fail in some other cases. For this reason do not use it in a production environment. And this is a temporary solution as I am sure the Node.js team will release a robust way to do it in a near future.
import path from 'path';
const __dirname = path.join(path.dirname(decodeURI(new URL(import.meta.url).pathname))).replace(/^\\([A-Z]:\\)/, "$1");
This code also works on Windows. (the replacement is safe on other platforms, since path.join
returns back-slash separators only on Windows)
As of Node.js 10.12 there's an alternative that doesn't require creating multiple files and handles special characters in filenames across platforms:
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));