-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
esm: add option to interpret __esModule like Babel #40892
Conversation
Adds an option `--cjs-import-interop`. When enabled, a CJS module will be translated to ESM slightly differently with respect to default exports. - When the module defines `module.exports.__esModule` as a truthy value, the value of `module.exports.default` is used as the default export. - Otherwise, `module.exports` is used as the default export. (existing behavior) It allows better interoperation between full ES modules and CJS modules transformed from ES modules by Babel or tsc. Consider the following example: ```javascript // Transformed from: // export default "Hello"; Object.defineProperty(module.exports, "__esModule", { value: true }); module.exports.default = "Hello"; ``` When imported from the following module: ```javascript import greeting from "./hello.cjs"; console.log(greeting); ``` With `--cjs-import-interop`, it will print "Hello". Fixes: nodejs#40891
Co-authored-by: Voltrex <[email protected]>
/cc @nodejs/modules |
I'm not a fan unfortunately. We had discussed this in the past at length @guybedford and I. In particular I don't think this should be a global flag. Needing to have continuous support for a global flag is honestly much more a burden than doing a per package or per module option to configure this. I personally think the evaluation prior to linkage causes other issues that don't act 100% like babel. Even with |
Thank you for the detailed feedback!
Is the discussion in a written form and public? If so, I'd like to look through the discussion for better design. I thought someone must have already considered the problem but I couldn't find relevant discussions.
I see. I'll try to design per-module options then. With that in mind, is it acceptable to keep the CLI option to determine the default? The following options came to my mind:
|
I'd say it is unlikely and probably could only be used for testing purposes. See examples of In recent times @GeoffreyBooth and I have thought to remove
I do not want this to happen. Absolutely not going to become the default. Becoming the default would mean a variety of CJS modules cannot use their full Currently, CJS compiled via babel and other tools works fine and with full capabilities but differently from some tools. This would cause another wave of needing to rewrite code. In particular I think it would be more realistic to change a default if all the tools agreed on behavior for |
I see. I also started to think it unnecessary to change the global default, recalling the original motivation. To provide a better migration path for downstream modules (including application codes), it is enough to give options to these downstream modules. So I'll try to switch behaviors based on the importing module's configuration. |
This is the kind of thing that would be better enabled via a loader rather than a global flag. See https://github.com/nodejs/loaders. Though if it's on the cjs side it might need to be in |
Closing it as well: see #40891 (comment) #40902 (comment) |
This PR adds an option
--cjs-import-interop
. When enabled, a CJS module will be translated to ESM slightly differently with respect to default exports.module.exports.__esModule
as a truthy value, the value ofmodule.exports.default
is used as the default export.module.exports
is used as the default export. (existing behavior)It allows better interoperation between full ES modules and CJS modules transformed from ES modules by Babel or tsc. Consider the following example:
When imported from the following module:
With
--cjs-import-interop
, it will print "Hello".Fixes: #40891