esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

ESBuild doesn't preserve `export *` from externalized packages consistently

Open dzearing opened this issue 4 years ago • 7 comments
trafficstars

I'm re-opening this due to getting buried and also because esbuild is producing fundamentally broken output. This could use some eyes.

Setup:

index.js:

export * from './utilities';

utilities.js:

export * from 'foo';

Now create an esm bundle:

esbuild --bundle index.js --outfile=out.js --format=esm --external:foo

Expected:

export * from 'foo';

Resulted:

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __reExport = (target, module, desc) => {
  if (module && typeof module === "object" || typeof module === "function") {
    for (let key of __getOwnPropNames(module))
      if (!__hasOwnProp.call(target, key) && key !== "default")
        __defProp(target, key, { get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable });
  }
  return target;
};

// index.js
var foo_exports = {};
__markAsModule(foo_exports);

// utilities.js
var utilities_exports = {};
__markAsModule(utilities_exports);
__reExport(utilities_exports, foo_star);
import * as foo_star from "foo";

// index.js
__reExport(foo_exports, utilities_exports);

This makes the bundle unusable in the browser; while I believe star exports are far more fragile than named exports when exporting from an external, it's still completely valid. When encountered, esbuild produces unusable results.

This problem does not repro if the export * from 'foo' is in the entry point (index.js) rather than the sub file (utilities.js).

dzearing avatar Nov 02 '21 21:11 dzearing

FWIW, this still repros @ 0.14.13.

dzearing avatar Jan 24 '22 22:01 dzearing

I don't understand why __reExport is used (at all) when the target format is ESM?

aleclarson avatar Feb 10 '22 01:02 aleclarson

Looks like files including import_star has been considered commonjs: https://github.com/evanw/esbuild/blob/ed341b0c7920d6638b872121ffc8e75e5761bdca/internal/bundler/linker.go#L1249-L1253

hyrious avatar Feb 10 '22 01:02 hyrious

Any movement on this? It's currently a full blocker on me moving to Vite.

taylorhadden avatar Jun 03 '22 14:06 taylorhadden

@evanw This is fairly easy to repro, and we are still working around this when we hit it. Basically it's very hard to prevent this from happening if you're bundling things that you don't control (like vendor packages.) Any way to prioritize fixing this one?

dzearing avatar Mar 20 '23 21:03 dzearing

How can we make sure we avoid a 3 year anniversary to this issue? It's pretty annoying...

datner avatar Jul 04 '23 19:07 datner