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

Output cjs chunk lost __esModule for es module. #3760

Closed
underfin opened this issue Sep 3, 2020 · 15 comments · Fixed by #3822
Closed

Output cjs chunk lost __esModule for es module. #3760

underfin opened this issue Sep 3, 2020 · 15 comments · Fixed by #3822

Comments

@underfin
Copy link

underfin commented Sep 3, 2020

Input

import {ssrRenderAttrs} from "@vue/server-renderer";
var script = {
  name: "PageB"
};
function ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
  _push(`<h1${ssrRenderAttrs(_attrs)}>I AM PAGE B</h1>`);
}
script.ssrRender = ssrRender;
export default script;

Output

"use strict";
var renderer = require("@vue/server-renderer");
var script = {
  name: "PageB"
};
function ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
  _push(`<h1${renderer.ssrRenderAttrs(_attrs)}>I AM PAGE B</h1>`);
}
script.ssrRender = ssrRender;
exports.default = script;

Original issues: vitejs/vite#764

The input is a chunk, not a entry.Maybe we should change this line to (this.facadeModule !== null).I'm not sure for this, hope get some help,thanks.
https://github.com/rollup/rollup/blob/master/src/Chunk.ts#L714-L716

Expected Behavior

Output cjs chunk should hsa __esModule for es module. Has code Object.defineProperty(exports, '__esModule', { value: true });

Actual Behavior

Output cjs chunk lost __esModule for es module.

@lukastaegert
Copy link
Member

So as I understand it, the issue is that auto-generated chunks do not have an __esModule property. The reasons are simple:

  • auto-generated chunks are always using named exports mode, unless they happen to coincide with an actual entry chunk. In the latter case, the exports mode is that of the entry chunk
  • auto-generated chunks are only meant to be consumed within the same Rollup build. It does not make any sense to put interop code into internal chunks where Rollup has full control over except to make things slower

So it looks like the defineAsyncComponent is a function that can accept various things, ranging from promises that directly resolve to components to ES module namespaces. Looking at the sniffing code, you look for either .__esModule or Symbol.toStringTag. The latter might be simulated via Rollup's namespaceToStringTag option, but I am not sure it is added if the exports of a chunk correspond to a namespace.

However I would wonder if there isn't a better to handle this than either mashing __esModule or toStringTags to every namespace. For instance, just looking for a .default property is a very viable heuristic that can work wonders here.

@underfin
Copy link
Author

underfin commented Sep 3, 2020

For instance, just looking for a .default property is a very viable heuristic that can work wonders here.

Yeah, that can be work fine as expected.But i think the cjs module output from es module should have __esModule flag as other bundle tools.The auto-generated chunks is not only use inside one app build by rollup, it sometimes can be used other app build by other bundle tools, it should be worked as expected in any scence.

@lukastaegert
Copy link
Member

Not sure. What you want is that the return value of a dynamic import has the __esModule property set. This is not the same thing as what this flag was originally meant to mean. Moreover, there is no guarantee that the target of a dynamic import is a file that only has the corresponding exports. Chunking could merge several files, in which case Rollup will in fact create a dynamic namespace object inside the chunk which is then extracted as a property from the exports object. For your logic to work, this dynamic namespace object would need to have the __esModule flag while it does not matter if the chunk itself has the flag. And it needs to have this flag for all output formats, even when creating ES module output because again the logic will fail because a bundled namespace object usually does not satisfy any of the conditions you are checking for. We could do this, but it feels weird and definitely not something that should happen by default because many will not need it. How are other bundlers handling this? Is Webpack adding an __esModule property to internal dynamic imports?

@lukastaegert
Copy link
Member

Ok, it appears that Webpack is actually going all the way, adding BOTH __esModule and namespaceToStringTag to dynamic namespaces, I'm impressed. The thing is, adding __esModule to namespace objects DOES solve an issue we have with the commonjs plugin in a more elegant way, maybe coupling it to the esmodule option. I will need to think about it.

@underfin
Copy link
Author

underfin commented Sep 4, 2020

Thanks for your explanation :)

@lukastaegert
Copy link
Member

Please check out #3764

@underfin
Copy link
Author

underfin commented Sep 6, 2020

Thanks for your quickly fix, it worked by expected.

@tbgse
Copy link

tbgse commented Oct 10, 2020

Hi @lukastaegert I've been following this issue closely, as well as your related PR that was merged for the commonjs plugin (rollup/plugins#552). No matter how i configure the plugin, it still seems like the output remains unchanged from before. Am I missing something? Did the change to the plugin actually resolve this issue or is there a reason that this issue is still open?

@lukastaegert
Copy link
Member

It should be resolved and this issues closed

@underfin
Copy link
Author

As @tbgse said, the issues is also happend. @lukastaegert can you re-have a look with this?

@lukastaegert
Copy link
Member

I am not sure how to verify this with the reproduction above, especially I am not 100% sure where to look as I cannot find the code snippet listed above anywhere in the output. So what the fix does NOT do: Inject the __esModule marker into the exporting chunk (unless it is an entry, in which case it should already happen). What it does instead is inject the __esModule marker at the import site by injecting a helper getAugmentedNamespace.

Further guidance would be appreciated especially to what the error is. Also you might want to update the repro with the latest released version of the plugin.

@lukastaegert
Copy link
Member

Ah, what it does not do in fact is inject the __esModule marker when using an import to import a CommonJS file. Now I remember. So the fix here should be to extend where Rollup injects the toStringTag instead. This fix is still missing, my bad.

@lukastaegert
Copy link
Member

@underfin There is now a proper fix at #3822, please check it out. It will not add the __esModule marker but rather 'Module' as Symbol.toStringTag and requires you to add the output.symbolToStringTag option. To my understanding this should solve the original issue as well?

@underfin
Copy link
Author

Yes.It worked fine by add output.namespaceToStringTag option :)

@lukastaegert
Copy link
Member

Awesome! Depending on feedback by @guybedford I will see this is released soon. Sorry for the wait!

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