We use cookies to enhance your experience on the site
CodeWorlds

Async Components & Suspense

In NOVA LAB heavy cargo modules aren't loaded immediately - the system loads them on demand, displaying status on screen. Vue offers async components - loading components lazily (on demand) and Suspense - control over the loading state.

defineAsyncComponent

Instead of importing a component directly, you can load it asynchronously:

1<script setup>
2import { defineAsyncComponent } from 'vue'
3
4// Simple lazy import
5const HeavyModule = defineAsyncComponent(
6  () => import('./HeavyModule.vue')
7)
8</script>
9
10<template>
11  <HeavyModule />
12</template>

The component is fetched only when it's needed (rendered in the template).

Advanced Configuration

1<script setup>
2import { defineAsyncComponent } from 'vue'
3import LoadingSpinner from './LoadingSpinner.vue'
4import ErrorDisplay from './ErrorDisplay.vue'
5
6const HeavyModule = defineAsyncComponent({
7  // Loader function
8  loader: () => import('./HeavyModule.vue'),
9
10  // Component displayed during loading
11  loadingComponent: LoadingSpinner,
12
13  // Delay before showing loading component (ms)
14  delay: 200,
15
16  // Component displayed when loading fails
17  errorComponent: ErrorDisplay,
18
19  // Timeout - after this time the error component is shown (ms)
20  timeout: 10000
21})
22</script>

Suspense

<Suspense>
is a built-in Vue component for managing the loading state of asynchronous components:

1<template>
2  <Suspense>
3    <!-- Main content (loaded component) -->
4    <template #default>
5      <HeavyModule />
6    </template>
7
8    <!-- Loading state -->
9    <template #fallback>
10      <div class="loading">
11        <p>Loading module...</p>
12        <div class="spinner"></div>
13      </div>
14    </template>
15  </Suspense>
16</template>

Suspense Events

Suspense emits events informing about the loading state:

1<template>
2  <Suspense
3    @pending="onPending"
4    @resolve="onResolve"
5    @fallback="onFallback"
6  >
7    <template #default>
8      <AsyncModule />
9    </template>
10    <template #fallback>
11      <LoadingSpinner />
12    </template>
13  </Suspense>
14</template>
15
16<script setup>
17const onPending = () => console.log('Loading started...')
18const onResolve = () => console.log('Loading complete!')
19const onFallback = () => console.log('Fallback displayed')
20</script>

Async Setup in Components

A component with

async setup
or top-level
await
automatically becomes an async dependency for Suspense:

1<!-- AsyncModule.vue -->
2<script setup>
3const data = await fetch('/api/module-data')
4  .then(r => r.json())
5</script>
6
7<template>
8  <div>{{ data.name }}</div>
9</template>
Go to CodeWorlds