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
Allow using objects as hooks to change execution order #4600
Conversation
Thank you for your contribution! ❤️You can try out this pull request locally by installing Rollup via npm install rollup/rollup#object-hooks or load it into the REPL: |
Codecov Report
@@ Coverage Diff @@
## master #4600 +/- ##
=======================================
Coverage 98.86% 98.87%
=======================================
Files 209 209
Lines 7345 7366 +21
Branches 2098 2102 +4
=======================================
+ Hits 7262 7283 +21
Misses 27 27
Partials 56 56
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
This is awesome! Thank you for working on it! 💚
In my personal opinion, I'd suggest that we don't do it now, but until there are valid cases for them. Deps on the use cases, we might come up with other options to add.
I agree |
Thanks for working on this @lukastaegert! About naming, same as Anthony,
I think I prefer B here, but both look fine.
Using |
Stupid question. but what would be the purpose of "execute"? |
|
Ah, of course you are right. Not sure we can (or should) enforce For the non-imperative form, it could just be |
At this point, the non-imperative form is beginning to look much more concise. |
Love |
Good point, even parallel hooks have a synchronous part that is executed in a specific order. |
This looks pretty good to me 😄 Would it make sense to update the PR description with the latest changes? I'm not 100% sure I have a full understanding of the current state of things |
c4b377a
to
b703d1b
Compare
Done. To sum it up so far I
I still did not get to implementing "sequential", and I am also considering extending support to sync hooks as well. |
+1 to extend the object form to sync hooks too. The |
Sync hooks are now supported as well. |
And finally,
|
About the execution order of parallel hooks when |
@patak-dev was there a usecase you had in mind for that behavior? @antfu's original proposal that's implemented here made sense to me because traditionally if a hook is parallel then it means you don't care about the order it's run in. I'm not opposed to the behavior you suggested, but it's not what I originally envisioned and am not quite sure when it would be necessary |
@patak-dev I must admit I must have slightly skipped over your comment😳 Yes, I can also implement it the other way. I am just very happy I decided to write documentation last 😅 |
The order of parallel hooks still matters. Each hook is executed in order and all the generated promises are then awaited: await Promise.all( hooks.map( h => h(...) ) The order of the sync part of each hook could allow a user to introduce custom synchronization even without the So, I think it should be the other way around. We should be looking for a usecase to justify We can let You can get the effect of the current implementation with a single plugin by using The implementation complexity is the same at this point, but I think the orthogonal flag will better play with other options we could add in the future. Each of them having a single effect is easier to teach and will end up allowing us to cover more use cases. |
I have changed the logic as suggested by @patak-dev and also extended it to include banner/footer/intro/outro
At this point, only documentation is missing, then this can be released. |
Documentation has been added as well. I will leave this PR open for a few days and then release it if there are no further comments. DocumentationInstead of a function, hooks can also be objects. In that case, the actual hook function (or value for
|
Created an RFC, but I'll drop a note so that we can have it mind for the design of the Some plugins need to run before or after a specific plugin (i.e. before or after the Vue or Svelte compiler transforms). Currently, Vite and Rollup do not provide an explicit API or plugins to collaborate with each other explicitly. As a result, userland plugins are resorting to hacks and workarounds to achieve a better UX. Extending {
name: 'vuetify:import',
transform: {
order: { post: 'vite:vue' },
async handler (code, id) {
...
},
},
} This would enable better compatibility between plugins that interact or extend each other, and result in a better user experience by removing the need to order plugins manually (in cases like these). |
I discussed with @ElMassimo his proposal, and @brillout proposed something similar in the linked Vite RFC. I was originally against adding more complex ordering, but now I think it is something worth exploring. Mainly because frameworks are already taking control and reordering the plugins in different ways, leading to potentially more confusion. One of the things I like about the hooks object form is that it will allow us to do extensions if needed in the future. So, I think we should move forward with this PR as is at this point. @ElMassimo, @brillout, I think that the best place to gather consensus about further ordering mechanisms is by starting a discussion on the Vite repo and involving the main frameworks. |
Sounds good to me 👌. Just opened a new discussion for this: vitejs/vite - #9613 - Hook ordering. @ElMassimo the discussion patak mentioned: vitejs/vite - #9442 - comment @brillout. @lukastaegert I think Rollup users would equally benefit from this. That's why I'm thinking it could/(should?) be a feature in Rollup land. |
Link for reference, here is the Vite PR for supporting object hooks on top of this PR As a side note: imagine this PR gets shipped in Rollup v2.78.0 or something, it will break the types for the current versions of Vite until the Vite PR gets merged. I didn't see a straightforward way to make it smoother so I guess it would be better to work closely on both sides and make the gap as narrower as possible. |
Would it be worthwhile to go for an intermediate Vite release where you use something like |
@lukastaegert we narrowed down the rollup version to 2.77 in vite 3.0.6 yesterday. So if you release this in 2.78, it should not affect Vite. |
Oh, we should also backport the narrowing down to Vite 2.9. I'll do that today Done, vite@2.9.15 is ready too |
Great work! If nothing else comes up, I plan on releasing this about this time tomorrow. |
Released in v2.78.0 |
based on recent [recent changes](rollup/rollup#4600) and upcoming [PR](vitejs/vite#9634)
This PR contains:
Are tests included?
Breaking Changes?
List any relevant issue numbers:
See https://github.com/vitejs/vite/discussions/9442 for context
Description
This PR will be released in a few days if there are no further comments.
This PR implements the following:
handler
property instead of a function:banner
,footer
,intro
,outro
, thehandler
can also be a string.order?: 'pre' | 'post' | null
that changes the execution order for this hook (similar to what Vite'senforce
currently does for all hooks):sequential: true
. When such a hook is encountered, all previous parallel plugin hooks will be awaited. Then the sequential hook will be executed and awaited before continuing with the next plugin. If none of them is sequential, the remaining plugin hooks will be executed in parallel again. This can be combined withorder
.Why not
enforce
at the top level?While the top level may be enough for simple plugins that only have a single hook, the problem of plugin ordering is not a problem of ordering all hooks, it is usually only the problem of ordering a single hook. A good example is the
commonjs
plugin: While it would want its transform hook to be executed at the user-provided order, theresolveId
hook needs to be executed before other plugins as it is needed to detect entry points (currently this is solved by injecting a secondary plugin in theoptions
hook, but this is probably not ideal).As it stands, my plan would be not to support top-level enforce at all but go with something like this. As this was born from discussions with the Vite people, they would likely support it as well if we align on all details.
Why the object form?
At various times it was suggested to add certain
preSomething
orpostSomething
hooks. I do not like the idea as they are just further polluting the number of available hooks and are themselves rather inflexible. With the proposed implementation, we can further refine things by allowing additional values or additional parameters on the object. Also, the original discussion started from the question if we cannot make certain parallel hooks sequential on demand. This could be added with another object property as well. But I decided to go for execution order first as it has more immediate use for Rollup itself.Why support it for all async hooks, not just non-parallel ones?
The goal is also to support making parallel hooks sequential. Before this is implemented, the object form does not hurt.