-
-
Notifications
You must be signed in to change notification settings - Fork 599
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
CommonJS plugin breaks isEntry for entry points #1169
Comments
Unfortunately, I could not get the plugin to work easily without proxying all entry points. In what way does the rust plugin rely on the toml file being marked as an entry? Could it be solved in another way? |
This is also a more general question as proxying entry points is a pattern that other plugins could use as well, I even promote it as a pattern for polyfill injection in the docs, but this should not break your plugin. |
What is the point of having an The Rust plugin uses You can see the code here: if the file is an entry, then it immediately loads the Wasm promise and uses However, if the file is not an entry, it returns a function which must be called by the importer to load the Wasm. In other words: if it's not an entry then it gives a function which will load the Wasm file asynchronously (via promises). But if it's an entry then it must automatically load the Wasm file, it cannot return a function. This is the behavior that users expect: if they're importing the Rust program as an entry point, then it should automatically run the Rust program (just the same as a JS program). |
The actual wrapper isn't the problem ( Why can't the CommonJS plugin just ensure that Also, why does the CommonJS plugin wrap non- |
After upgrading to v22.0.0, I'm no longer able to build; getting an error similar to |
Likely because you have a plugin that relies on the module id (eg. Either the other plugins need to strip queries, or |
Yea it's actually the eslint plugin (@rbnlffl/rollup-plugin-eslint). Should I report this as a bug? Or is there a temporary workaround? |
I thought we'd moved that plugin here. |
Ah, I didn't realize there's actually an official plugin for eslint over here. That plugin seems to be regularly updated too, not sure whether it's needed then. Anyway, I replaced that plugin with the official one and got this error:
edit: After adding the
I tried adding |
I will see if I can reduce entry proxying. In any case @Pauan your solution is still fragile in so far as there is a race condition depending on whether a A better solution, though, is to hook into const entrySuffix = '?rust-entry';
// ...
function rust() {
// ...
return {
// ...
async resolveId(id, importer, options) {
if (options.isEntry && $path.basename(id) === "Cargo.toml") {
// turn into absolute path the same way Rollup would resolve it
const resolvedId = $path.resolve(id);
return `${resolvedId}${entrySuffix}`;
}
// ... other code
}
load(id) {
if (id.endsWith(entrySuffix) {
return `import wasm from ${JSON.stringify(id.slice(0, -entrySuffix.length))}; wasm();`
}
// ... other code
}
}
} That way, it should even be possible to use the same toml file as both an entry point and a dependency in the same graph and the "right" thing should happen depending on whether the entry point is called first or it is first used as a dependency. Depending on how you do it, this could actually make your code nicer in other places as that way, you can unify the logic of entry points and non-entry points. |
fwiw, this just caught me out too. I had a plugin that wasn't expecting the query to appear at the end of the |
That's good to know, I will use that solution, thanks. |
@lukastaegert I changed rollup-plugin-rust so that it uses resolveId + load instead of transform. This does fix the isEntry problem, and now it works properly even if a However, there is still one issue: if the user does this, then everything is perfect... export default {
plugins: [
rust(),
nodeResolve(),
commonjs(),
],
}; ...but if the user does this instead... export default {
plugins: [
nodeResolve(),
commonjs(),
rust(),
],
}; ...then everything seems to work okay (no warnings or build errors), but at runtime everything is broken because nodeResolve has a So why is the nodeResolve plugin changing non- This is a horrible user experience: if the user puts the plugins in the wrong order then they get no warning or build error, but things mysteriously break at runtime. And they break in a really subtle way which is hard to debug. I know this is an issue with nodeResolve and not commonjs, but it seems to be a part of a general pattern of plugins not having a good way to preserve isEntry for other plugins. If proxies are supposed to be a common pattern, then the proxies need to not break isEntry. |
Admittedly I am not sure why node-resolve would interfere here. In any case, there is a pattern to protect against over-eager options(rawOptions) {
// We inject the resolver in the beginning so that "catch-all-resolver" like node-resolver
// do not prevent our plugin from resolving entry points ot proxies.
const plugins = Array.isArray(rawOptions.plugins)
? [...rawOptions.plugins]
: rawOptions.plugins
? [rawOptions.plugins]
: [];
plugins.unshift({
name: 'commonjs--resolver',
resolveId
});
return { ...rawOptions, plugins };
} |
Maybe at some point we should take a leaf out of Vite's book and add our own "enforce: 'pre'" option |
#1180 will avoid proxying for non-cjs entry points, I think that will make everyone happier |
That's great news, though it doesn't fix the specific issue with rollup-plugin-rust, since that issue is with node-resolve, not commonjs. Using |
While the "hack" would give you a way to solve the issue independently and quickly (and I do not think it is really terrible: Sometimes you just really want a hook to tun first or last and need to override ordering by users). Still, here is my proposal for a long-term solution in node-resolve: If you can verify that this solves the issues, that would help in getting it merged. |
@lukastaegert Sorry for the delay. Although that PR does fix the immediate issue, I have an idea: Right now the {
id: string,
external: boolean | "absolute",
moduleSideEffects: boolean | 'no-treeshake',
syntheticNamedExports: boolean | string,
meta: {[plugin: string]: any},
resolvedBy: string | null,
} The new So instead of checking the id, the node-resolve plugin would check the The advantage is that this will work even if a plugin doesn't change the id, but instead changes other settings (like This is essentially the same as |
Sounds like an idea. PR welcome if you want to speed up things. |
Hi guys,
solved by downgrading |
I'm having the same error as @luckylooke. I followed the recommendation and added
No matter what I do, I can't seem to get the eslint plugin to agree that |
Expected Behavior
The console should contain the following:
Actual Behavior
The console contains the following:
This means that the entry point is returning
isEntry: false
even though it should returnisEntry: true
Additional Information
I noticed this bug while using the Rust Rollup plugin. With that plugin, you can import
Cargo.toml
files:The Rust plugin requires
isEntry
in order to generate correct code.However, even though those
Cargo.toml
files are not CommonJS (they're not even JS!) the commonjs plugin breaks them by causingisEntry
to returnfalse
even though it should returntrue
.The text was updated successfully, but these errors were encountered: