One exciting feature of Vue 3 is Suspense. It is a built-in component that makes loading state orchestration much simpler.
⚠️ Disclaimer: Suspense is an experimental feature and the API might change before reaching the stable release.
To demonstrate the problem, imagine a nested hierarchy of multiple components that are either lazy-loaded or require data fetching from a remote service. Each component has to handle its own loading state, and the UI jumps around, causing layout shifts which negatively affect your core web vitals.
The problem is evident from the video below.
Multiple loading states and layout shifts result in a frustrating user experience.
PermalinkSuspense
The suspense element has two slots named #default
and #fallback
and both of them have one immediate child node. While the default slot is loading, the fallback is displayed.
<Suspense>
<!-- component with nested async dependencies -->
<Links />
<!-- loading state via #fallback slot -->
<template #fallback>
<Loader />
</template>
</Suspense>
Suspense, will automatically detect any async components or async setup hooks and will wait for both of them to be fulfilled until the default slot is displayed.
For our example, we need to wrap all the sections to the Suspense element and move the loader logic from each component to the fallback section.
<template>
<HelloWorld msg="Hello Vue 3!" />
<Suspense>
<div>
<TheEcosystem />
<ThePlugins />
<TheLinks />
</div>
<template #fallback>
<loadingComponent />
</template>
</Suspense>
</template>
You can tell the difference from the video below.
We eliminated multiple UI layout shifts, and the code is now much cleaner after removing multiple loading states. Nice work! 👏👏👏
PermalinkAdditional resources:
Vue Suspense — Everything You Need to Know by Michael Thiessen
Easy Loading Pages With Vue Suspense (video) by John Komarnicki
Async with Suspense by Marina Mosti