Don’t use URL to construct paths in Node.js

I’ve been spending some of my time recently making sure WordPress Playground works in Windows.
While working on Windows fixes I learned a lot about making sure Javascript code works POSIX and Windows when running it in Node.js.

One thing that I learned is that you shouldn’t use URL to construct paths.

If you construct a path using new URL(import.meta.url) in Node.js and use pathname to to obtain the path, it will always have a leading slash in front of the path.
This is ok for POSIX but in Windows it results in invalid paths
like /C:/Users/.

What to use instead of URL

You can use fileURLToPath from the URL package, it will correctly construct both POSIX and Windows paths from file:/// paths.

Polyfilling __dirname and __filename in Node 20+

In Node 20 and above you can use import.meta.filename and import.meta.dirname to polyfill __dirname and __filename.

Example

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

const windowsImportMetaUrl = "file:///C:/Users/me/Downloads/index.js";
console.log('windowsImportMetaUrl', windowsImportMetaUrl);

let __dirname = new URL('.', windowsImportMetaUrl).pathname;
let __filename = new URL(windowsImportMetaUrl).pathname;
console.log('__filename', __filename);
console.log('__dirname', __dirname);


__filename = fileURLToPath(
    windowsImportMetaUrl,
    {
        windows: true,
    }
);
__dirname = path.win32.dirname(__filename);
console.log('__filename', __filename);
console.log('__dirname', __dirname);

__filename = import.meta.filename;
__dirname = import.meta.dirname;
console.log('__filename', __filename);
console.log('__dirname', __dirname);

The above code will result in:

windowsImportMetaUrl file:///C:/Users/me/Downloads/index.js

# new URL output 
__filename /C:/Users/me/Downloads/index.js
__dirname /C:/Users/me/Downloads/


# fileURLToPath output
__filename C:\Users\me\Downloads\index.js
__dirname C:\Users\me\Downloads


# import.meta.filename and import.meta.dirname output
__filename C:\Users\me\Downloads\index.js
__dirname C:\Users\me\Downloads

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *