-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
perf: improve VNode creation performance with compiler hints #3334
Conversation
Since Also this means when |
* - context.forSSR = true | ||
* see `subTransform` in `ssrTransformCompoent.ts` | ||
*/ | ||
forSSR?: boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name can be a bit confusing here. Maybe something more explicit like ssrClientBranch
?
Alright, didn't notice it |
I adjusted the PR and updated the initial proposal above. About the context.ssr = true
context.ssrClientBranch = false // default
context.ssrClientBranch = true // when compiling the fallback branch |
This PR is backward compatible, but not forward compatible. This means that if a third-party library is built with this PR, then this library cannot be used in the lower version of the Vue runtime. But it does not affect the user to use the old library |
I think this is worth it - we probably will have to introduce a "semi breaking change" in 3.1 where pre-compiled components using version >=3.1.0 will not work with runtime <3.1.0. Btw it needs to be rebased now |
Should be fine now |
Note: I noticed that we still have mostly duplicated logic in Since the gain in Did a simple benchmark and I also noticed a downside of the pre-normalized shape flags, as they result in a lot of extra // before
createVNode('div', null, 'foo')
// after
createElementVNode('div', null, 'foo', null, null, 9 /* shapeFlag */) I tested it in a medium sized project and the Since we are already separating element vs. component vnodes, we know that for compiled element vnodes they can only have text or array children. So I added a simpler children shapeFlag check for |
Hello thank you a lot for the work here. It will sounds like a dumb questions... So with this PR we can't build anymore universal component library with vue demi right for vue2 and vue3 ? Because unfortunately there is still a lot of companies that keep using vue2 and not already started the transition that would want to build vue3 design system without having to rewrite it after when they finally transition to vue3. Can we have a clear explanations / documentations about how to achieve that and where this break. I understand there is a lot of work to do but if you want companies to follow we need a way more better documentation / support on that. Even after looking at existing ui libs no ones is doing this kind of transition. It's build vue3 right now or stay with the vue2. And for most of them none of them have finished the transition... I hope this message will be listened. Have a great weekend |
Background
The original idea came from @yyx990803, and I explored it.
We are currently doing a LOT of runtime checks in createVNode which is probably the most important perf hot spot. And these can be skipped by the compiler hints.
Differentiate element vs component vnodes
Add dedciated
createElementVNode
andcreateComponentVNode
methods.the
createElementVNode
can skip:Both methods makes assumptions about pre-normalized inputs (listed below)
Props proxy check
We check isProxy(props) in case it's a user reactive object. For both
createElementVNode
andcreateComponentVNode
this can be skipped by lifting this check to the generated code instead.The guard code is only needed if a single
v-bind
is used:output:
In other cases it's either an object literal, or
mergeProps
will be generated which already spreads the object.Pre-normalize classes and styles
We currently check and normalize class and style when creating vnode, which can be done on-demand by compiling.
class/style
don't need normalization and can be generated as-is:output:
class/style
needs to be wrapped bynromalizeClass/normalizeStyle
output:
v-bind
:output:
normalizeProps
is used to normalize bothclass
andstyle
.normalizeProps
:output:
Pre-nomralize ShapeFlag
createElementVNode
'sshapeFlag
can be full static analyzed and the shapeFlag check can be skipped:ShapeFlags.ELEMENT
text
,array
ornull
createElementVNode
to also skip normalizeChildren and suspense children check.createComponentVNode
Suspense
&Teleport
shape flags can be statically analyzedStateful
vs.Functional
still needs to be determined at runtimenormalizechildren
for components to be safe.This should allow
createElementVNode
to be as efficient as possible.