Under The Hood
frontend vue Vue 3.x

<Suspense> Boundary and defineAsyncComponent() Loading Orchestration

Last updated
Prerequisites:
Vue 3 `<script setup>` with top-level `await`
Dynamic imports `import()`
  • vue
  • suspense
  • defineAsyncComponent
  • async
  • code-splitting
  • loading

Read at your depth

The practical view

`<Suspense>` is a built-in component that orchestrates nested asynchronous dependencies in the component tree. It provides two slots: `#default` (your async components) and `#fallback` (the loading indicator). An async dependency is any component using top-level `await` in `<script setup>` or loaded via `defineAsyncComponent(() => import('./Child.vue'))`. `<Suspense>` waits for all nested async children to resolve before revealing the tree.

The same idea in other frameworks

react equivalent
`<Suspense fallback={<Loading />}><AsyncChild /></Suspense>` catching thrown promises.

Legacy vs modern

Per-Component Loading Spinners vs Coordinated <Suspense>

Multiple independent loading spinners create visual layout thrashing; `<Suspense>` coordinates nested async children into one fallback.

before → after
Scattered Individual Spinners
<div v-if="loading">Spinner</div><div v-else>Content</div> // ❌ Staggered pop-in
Coordinated Vue <Suspense>
<Suspense><template #default><Dashboard /></template><template #fallback><Skeleton /></template></Suspense> // ✅ NEW

Interview gotchas

Context

Interviewers test your understanding of what triggers the Suspense boundary.

The mechanical answer

A component is treated as an async dependency by `<Suspense>` if: (1) it uses **top-level `await`** inside `<script setup>`, (2) its `setup()` hook returns a `Promise`, or (3) it is loaded via **`defineAsyncComponent()`**.

Trap

A component that performs data fetching inside `onMounted(async () => ...)` is NOT an async dependency for Suspense because `setup()` finishes synchronously.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.