Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a shim function for unbundled uses of require #1291

Merged
merged 1 commit into from
May 15, 2021
Merged

Conversation

evanw
Copy link
Owner

@evanw evanw commented May 15, 2021

Modules in CommonJS format automatically get three variables injected into their scope: module, exports, and require. These allow the code to import other modules and to export things from itself. The bundler automatically rewrites uses of module and exports to refer to the module's exports and certain uses of require to a helper function that loads the imported module.

Not all uses of require can be converted though, and un-converted uses of require will end up in the output. This is problematic because require is only present at run-time if the output is run as a CommonJS module. Otherwise require is undefined, which means esbuild's behavior is inconsistent between compile-time and run-time. The module and exports variables are objects at compile-time and run-time but require is a function at compile-time and undefined at run-time. This causes code that checks for typeof require to have inconsistent behavior:

if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
  console.log('CommonJS detected')
}

In the above example, ideally CommonJS detected would always be printed since the code is being bundled with a CommonJS-aware bundler. To fix this, esbuild will now substitute references to require with a stub __require function when bundling if the output format is something other than CommonJS. This should ensure that require is now consistent between compile-time and run-time. When bundled, code that uses unbundled references to require will now look something like this:

var __require = (x) => {
  if (typeof require !== "undefined")
    return require(x);
  throw new Error('Dynamic require of "' + x + '" is not supported');
};
var __commonJS = (cb, mod) => () => (mod || cb((mod = {exports: {}}).exports, mod), mod.exports);
var require_example = __commonJS((exports, module) => {
  if (typeof __require === "function" && typeof exports === "object" && typeof module === "object") {
    console.log("CommonJS detected");
  }
});
require_example();

Fixes #1202

@arcanis
Copy link

arcanis commented Jul 8, 2021

Annoyingly, this breaks passing the output of ESBuild into Webpack (like we do in our incremental migration, until all the loaders we need are available), since Webpack reports the shim as a fully dynamic require and is unable to apply static analysis to the require we marked as external.

Repository owner deleted a comment from beryllium76 Jul 9, 2021
@anchengjian
Copy link

how to remove this shim function ???

@tuchuants
Copy link

This commit broke require.resolve functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

environment detection broken in esbuild 0.11.11
4 participants