feat: introduce suspensible option to <Suspense> to fix suspense flicks #6736
Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
Resolve #5513
This PR introduces a new prop for
Suspense
-<Suspense suspensible>
to allow nested suspense to be captured by the parent suspense.Reproduction
Thanks a lot to @danielroe for the great reproduction:
https://stackblitz.com/edit/vitejs-vite-ftc8df?file=src%2FApp.vue
The Problem
When we have multiple async components like:
Suspense
creates a boundary that will resolve all the async components down the tree, which is how it is expected to be.When both async components need to be async (nested route page for example)
At the initial mount, it works as expected, both
DynamicAsyncOuter
andDynamicAsyncInner
are waited before rendering.The problem comes with patching. When we change
DynamicAsyncOuter
, Suspense awaits it correctly, but when we changeDynamicAsyncInner
, the Suspense does not get patched causing the nestedDynamicAsyncInner
renders an empty node until it has been resolved, causing the flickering.In order to solve that, we could have a nested suspense to handle the patch for the nested component, like:
This solves the patching issue but makes the mounting break as the nested Suspense now behaves like a sync component and has its own fallback.
The Solution
This PR introduces a new prop for
Suspense
-<Suspense suspensible>
to allow nested suspense to be captured by the parent suspense. Making it able to handle async patching for branches and keep the mount as one render to avoid flickering.Unlike async components,
Suspsense
'ssuspensible
prop is the default to false in order to not break the current behavior.