-
-
Notifications
You must be signed in to change notification settings - Fork 109
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
Improving the plugin API #452
Comments
Chatted a bit with @matias-capeletto from vite today and one of their learnings is that they should've made the EDIT: Relevant issue for that on the vite issue tracker: vitejs/vite#1815 Another thought that came up is that prefixes could be converted to search paramters. Search paramters are valid by default in URLs and thereby making them a valid import specifier. This is another alternative of doing prefix we should think about. // with prefix
import foo from "url:./bar/image.jpg";
// vs with search param
import foo from "./bar/image.jpg?url"; |
About the need of adding It may be a bit late to modify this in Vite now though, as it would be a breaking change, we discussed that in the linked issue. In Vite we can not place the user plugins directly at the start, as some core plugins are needed first. I was proposing that they will go before the feature core plugins (like json support). Evan pointed out issues with this idea though vitejs/vite#1815 (comment). I don't know if there is a clear strategy without having extra options in rollup hooks (like being able to bail out in non-first hooks) |
As for Plugin ordering: to set the enforce mode for Rollup plugin, I'd suggest passing it as an argument. Something like this: config.pushPlugin(someRollupPlugin(), 'pre') |
@piotr-cz With #438 we're moving away from plugins manually pushing stuff into wmr's internal state. Instead, the return value of plugins will be deeply merged into our state object. Before wmr does its job we currently presort the plugins array based on the I'm unsure how the proposed |
Rollup Plugins can still be used when import eslint from "@rollup/plugin-eslint"
export default {
plugins: [
{
...eslint({ include: '**/*.+(vue|js|jsx|ts|tsx)' }),
enforce: 'pre',
apply: 'build',
},
]
} |
@marvinhagemeister @matias-capeletto This answers my concern |
The current plugin API has served us well as a start, but it's not without its problems. Let's look at the common pitfalls with the current API:
\0
and\b
in paths. Just testing for an extension/\.js$/
is not enough. This breaks people's assumption about file paths. Examples of internal plugins where we need additional null byte checks:1) Path handling
I feel like 1) can be solved by reversing the relationship between our plugin container and plugins. Instead of putting the onus on each plugin to specify what it can't work with, it should specify what it can work with.
Current Plugin API:
We could in theory eliminate the first
\0
or\b
check if we'd replace that with aninternal:
prefix. This eliminates two edge cases at once.The above is a good improvement and we could even export a nice helper to abstract prefix handling away:
If we want to match for a particular prefix, we'd need to pass an additional property:
The above is great step forward, but it still requires the user to be aware of prefixes and remember to add the safeguard themselves. They can still shoot themselves in the foot by forgetting that or opting to manually test against
id
.Interestingly,
esbuild
has removed the chance of error by favoring a callback-style API:A benefit of the callback-style approach is that it is a way to get rid of the implicit
this
in our current plugins.Current API:
vs callback-style API:
It's definitely more to type, but would make it more explicit which functions are available and where they are coming from.
2) Plugin ordering
All plugins are currently called after built-in ones have run. This poses problems when a user plugin needs to intercept resolution before that or transform JSX before WMR has processed it. The current control flow roughly looks like this:
Similar to vite and webpack we can add additional phases where plugins can run.
To specify during which phase a plugin should run, we can add an
enforce
property, similar to vite.Seeing that both the webpack and vite ecosystem don't have known issues with plugin ordering that I'm aware of this seems to be a good solution.
3) Config hooks instead of mutating options
The third issue of users being able to mutate options and somewhat internal state directly can be solved by adding an addition
config()
hook. The return value of that will be deeply merged into the existing config.To avoid a tree-like structure of plugins, returning plugins from
config()
is disallowed.Instead, multiple plugins can return an array of plugins to allow for preset-style plugins. The returned array will be flattened into
options.plugins
internally:Related issues
Related PRs
The text was updated successfully, but these errors were encountered: