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

Regression of import statement when targeting CJS #2019

Closed
jacob-ebey opened this issue Feb 15, 2022 · 2 comments
Closed

Regression of import statement when targeting CJS #2019

jacob-ebey opened this issue Feb 15, 2022 · 2 comments

Comments

@jacob-ebey
Copy link

When importing the uuid package, this should be marked with __toModule, instead it's marked with __reExport.

This is a regression and breaks codebases that previously worked.

https://github.com/jacob-ebey/esbuild-import-regression

@hyrious
Copy link

hyrious commented Feb 15, 2022

Since 0.14.5, esbuild's interop between cjs → esm has been changed to be the same as other front-end bundlers when not using .mjs/.mts/.cts extensions. i.e. import default_name will always be exports.default if exports.__esModule is true.

This is the convension in front-end. If you bring that to node, something like this (the uuid package defined __esModule, and its default prop is undefined, which means he doesn't want you to import its default name) will break.

In short, you can change the filename extension to .mjs/.mts/.cts to bring back old behavior like 0.13.x. Or edit your code to import * as uuid from "uuid".

@evanw why don't we make node behavior as default when platform is node? I guess that way we may never have a chance to use current behavior then it will break other packages.

@evanw
Copy link
Owner

evanw commented Feb 16, 2022

The description above is accurate. Version 0.14.5 deliberately changed esbuild's handling of default imports to match Webpack. Your code is also broken when it's bundled with Webpack:

$ webpack build --stats errors-warnings --mode=development ./index.js
WARNING in ./index.js 3:12-19
export 'default' (imported as 'uuid') was not found in 'uuid' (possible exports: NIL, parse, stringify, v1, v3, v4, v5, validate, version)
webpack compiled with 1 warning

$ node dist/main.js
webpack://expected/./index.js?:5
console.log(uuid__WEBPACK_IMPORTED_MODULE_0__["default"].v4());
                                                         ^

TypeError: Cannot read properties of undefined (reading 'v4')
    at eval (webpack://expected/./index.js?:5:58)
    at Object../index.js (./esbuild-import-regression/expected/dist/main.js:19:1)
    at __webpack_require__ (./esbuild-import-regression/expected/dist/main.js:193:41)
    at ./esbuild-import-regression/expected/dist/main.js:233:37
    at Object.<anonymous> (./esbuild-import-regression/expected/dist/main.js:235:12)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)

The rationale is that since Webpack is used much more than esbuild, packages in the wild already have to be tuned for Webpack's behavior so matching Webpack's behavior in this case is a reasonable decision. The easiest way to get this to work is to avoid a default import:

-import uuid from "uuid";
+import * as uuid from "uuid";

Closing as by design.

why don't we make node behavior as default when platform is node? I guess that way we may never have a chance to use current behavior then it will break other packages.

That would make the rules around default more complex and would deviate from Webpack. I'm not convinced that that's a good idea since it seems like it would exacerbate the interop headaches around this edge case.

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

No branches or pull requests

3 participants