privatenumber / pkgroll

📦 Zero-config package bundler for Node.js + TypeScript
MIT License
1.01k stars 23 forks source link

shims for __dirname so one code can output to both esm and cjs #61

Closed wighawag closed 2 months ago

wighawag commented 2 months ago

Feature request

shim for _dirname or other features like this

This is something tsup supports (and esbuild) : https://github.com/egoist/tsup/blob/00188a0dc848c48fac45de245d1e021f370a84a3/src/cli-main.ts#L91

Motivations

My project export to both cjs and esm and being able to use the same code for both is needed

Alternatives

No response

Additional context

No response

Contributions

privatenumber commented 2 months ago

You mean you'd like to use __dirname in ESM?

CommonJS is being phased out by Node in favor of the ESM standard, so it might be better to shim import.meta.url for CJS. I haven't tested yet but this might even work in CJS already.

wighawag commented 2 months ago

I ended up using the following

import {dirname} from 'path';
import {fileURLToPath} from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));

and it indeed seems to be working

in the cjs it get transformed into :

path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));

So I guess this works, not sure why it is that verbose though

privatenumber commented 2 months ago

There are more concise options: https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-js-when-using-es6-modules

const __dirname = import.meta.dirname;
const __filename = new URL('', import.meta.url).pathname;
const __dirname = new URL('.', import.meta.url).pathname;

Anyway, closing as import.meta.url should be used.