evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.12k stars 1.15k forks source link

[feat] auto shim `import.meta.url` for cjs output #3099

Open JounQin opened 1 year ago

JounQin commented 1 year ago

Like rollup, it shims import.meta.url with the following codes:

(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('test.js', document.baseURI).href))

Additionally, there is an official rollup plugin @rollup/plugin-esm-shim which adds __filename, __dirname, require support for ESM automatically, maybe it can be adapted as an esbuild plugin also.

so1ve commented 1 year ago

Like rollup, it shims import.meta.url with the following codes:

(typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('test.js', document.baseURI).href))

Additionally, there is an official rollup plugin @rollup/plugin-esm-shim which adds __filename, __dirname, require support for ESM automatically, maybe it can be adapted as an esbuild plugin also.

Out of scope, just curious: Why rollup uses require('u' + 'rl') instead of a direct require?

hyrious commented 1 year ago

Why rollup uses require('u' + 'rl') instead of a direct require?

Because certain bundlers (including Rollup itself) won't try to bundle 'url' when it is not a trivial string.

$ echo 'require("url")' > a.js
$ npx rollup a.js -p commonjs

a.js → stdout...
import 'url';

var a = {};

export { a as default };
(!) Unresolved dependencies
https://rollupjs.org/troubleshooting/#warning-treating-module-as-external-dependency
url (imported by "url?commonjs-external")
$ echo 'require("u" + "rl")' > a.js
$ npx rollup a.js -p commonjs

a.js → stdout...
function commonjsRequire(path) {
    throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}

var a = {};

commonjsRequire("u" + "rl");

export { a as default };

However, this technique is not applied to esbuild -- https://esbuild.github.io/api/#non-analyzable-imports, esbuild can bundle 'url' in this form. 🤷