Async Components â
Basic Usage â
āĻŦāĻĄāĻŧ āĻ
ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāĻžāύāĻā§āϞāĻŋāϤā§, āĻāĻŽāĻžāĻĻā§āϰ āĻ
ā§āϝāĻžāĻĒāĻāĻŋāĻā§ āĻā§āĻ āĻā§āĻ āĻāĻŖā§āĻĄā§ āĻāĻžāĻ āĻāϰāϤ⧠āĻšāĻŦā§ āĻāĻŦāĻ āĻĒā§āϰāϝāĻŧā§āĻāύ āĻšāϞā§āĻ āϏāĻžāϰā§āĻāĻžāϰ āĻĨā§āĻā§ āĻāĻāĻāĻŋ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āϞā§āĻĄ āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤ āĻāĻāĻŋ āϏāĻŽā§āĻāĻŦ āĻāϰāĻžāϰ āĻāύā§āϝ, Vue āĻāϰ āĻāĻāĻāĻŋ defineAsyncComponent
āĻĢāĻžāĻāĻļāύ āϰāϝāĻŧā§āĻā§:
js
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => {
return new Promise((resolve, reject) => {
// ...load component from server
resolve(/* loaded component */)
})
})
// ... use `AsyncComp` like a normal component
āĻāĻĒāύāĻŋ āĻĻā§āĻāϤ⧠āĻĒāĻžāĻā§āĻā§āύ, defineAsyncComponent
āĻāĻāĻāĻŋ āϞā§āĻĄāĻžāϰ āĻĢāĻžāĻāĻļāύ āĻā§āϰāĻšāĻŖ āĻāϰ⧠āϝāĻž āĻāĻāĻāĻŋ āĻĒā§āϰāϤāĻŋāĻļā§āϰā§āϤāĻŋ āĻĒā§āϰāĻĻāĻžāύ āĻāϰā§āĨ¤ āϝāĻāύ āĻāĻĒāύāĻŋ āϏāĻžāϰā§āĻāĻžāϰ āĻĨā§āĻā§ āĻāĻĒāύāĻžāϰ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āϏāĻāĻā§āĻāĻž āĻĒā§āύāϰā§āĻĻā§āϧāĻžāϰ āĻāϰā§āĻā§āύ āϤāĻāύ āĻĒā§āϰāϤāĻŋāĻļā§āϰā§āϤāĻŋāϰ resolve
āĻāϞāĻŦā§āϝāĻžāĻ āĻāϞ āĻāϰāĻž āĻāĻāĻŋāϤāĨ¤ āĻāĻĒāύāĻŋ āϞā§āĻĄ āĻŦā§āϝāϰā§āĻĨ āĻšāϝāĻŧā§āĻā§ āύāĻŋāϰā§āĻĻā§āĻļ āĻāϰāϤ⧠reject(reason)
āĻāϞ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
ES āĻŽāĻĄāĻŋāĻāϞ āĻĄāĻžāĻāύāĻžāĻŽāĻŋāĻ āĻāĻŽā§āĻĒā§āϰā§āĻ āĻāĻāĻžāĻĄāĻŧāĻžāĻ āĻāĻāĻāĻŋ āĻĒā§āϰāϤāĻŋāĻļā§āϰā§āϤāĻŋ āĻĒā§āϰāĻĻāĻžāύ āĻāϰā§, āϤāĻžāĻ āĻŦā§āĻļāĻŋāϰāĻāĻžāĻ āϏāĻŽāϝāĻŧ āĻāĻŽāϰāĻž āĻāĻāĻŋāϰ āϏāĻžāĻĨā§ āĻāĻāϤā§āϰ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦ fineAsyncComponent
. Vite āĻāĻŦāĻ āĻāϝāĻŧā§āĻŦāĻĒā§āϝāĻžāĻā§āϰ āĻŽāϤ⧠āĻŦāĻžāύā§āĻĄāϞāĻžāϰāĻā§āϞāĻŋāĻ āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏ āϏāĻŽāϰā§āĻĨāύ āĻāϰ⧠(āĻāĻŦāĻ āĻāĻāĻŋāĻā§ āĻŦāĻžāύā§āĻĄā§āϞ āϏā§āĻĒā§āϞāĻŋāĻ āĻĒāϝāĻŧā§āύā§āĻ āĻšāĻŋāϏāĻžāĻŦā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻŦā§), āϤāĻžāĻ āĻāĻŽāϰāĻž āĻāĻāĻŋ Vue SFC āĻāĻŽāĻĻāĻžāύāĻŋ āĻāϰāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŋ:
js
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
)
āĻĢāϞāϏā§āĻŦāϰā§āĻĒ AsyncComp
āĻšāϞ āĻāĻāĻāĻŋ āϰâā§āϝāĻžāĻĒāĻžāϰ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āϝāĻž āĻļā§āϧā§āĻŽāĻžāϤā§āϰ āϞā§āĻĄāĻžāϰ āĻĢāĻžāĻāĻļāύāĻā§ āĻāϞ āĻāϰ⧠āϝāĻāύ āĻāĻāĻŋ āĻāϏāϞ⧠āĻĒā§āώā§āĻ āĻžāϝāĻŧ āϰā§āύā§āĻĄāĻžāϰ āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āĻāĻĒāϰāύā§āϤā§, āĻāĻāĻŋ āϝā§āĻā§āύ⧠āĻĒā§āϰāĻĒāϏ āĻāĻŦāĻ āϏā§āϞāĻ āĻŦāϰāĻžāĻŦāϰ āĻ
āĻā§āϝāύā§āϤāϰā§āĻŖ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§ āĻāϞ⧠āϝāĻžāĻŦā§, āϤāĻžāĻ āĻāĻĒāύāĻŋ āĻ
āϞāϏ āϞā§āĻĄāĻŋāĻ āĻ
āϰā§āĻāύā§āϰ āϏāĻŽāϝāĻŧ āĻŽā§āϞ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻāĻŋāĻā§ āύāĻŋāϰā§āĻŦāĻŋāĻā§āύ⧠āĻĒā§āϰāϤāĻŋāϏā§āĻĨāĻžāĻĒāύ āĻāϰāϤ⧠āĻ
ā§āϝāĻžāϏāĻŋāĻā§āĻ āϰâā§āϝāĻžāĻĒāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
āϏāĻžāϧāĻžāϰāĻŖ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞāĻŋāϰ āĻŽāϤā§, async āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞāĻŋ app.component()
āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠registered globally āĻšāϤ⧠āĻĒāĻžāϰā§:
js
app.component(
'MyComponent',
defineAsyncComponent(() => import('./components/MyComponent.vue'))
)
āĻāĻā§āϞāĻŋ āϏāϰāĻžāϏāϰāĻŋ āϤāĻžāĻĻā§āϰ āĻŽā§āϞ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āĻāĻŋāϤāϰā§āĻ āϏāĻāĻā§āĻāĻžāϝāĻŧāĻŋāϤ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§:
vue
<script setup>
import { defineAsyncComponent } from 'vue'
const AdminPage = defineAsyncComponent(() =>
import('./components/AdminPageComponent.vue')
)
</script>
<template>
<AdminPage />
</template>
Loading and Error States â
āĻ
ā§āϝāĻžāϏāĻŋāĻā§āĻā§āϰā§āύāĻžāϏ āĻ
āĻĒāĻžāϰā§āĻļāύ⧠āĻ
āύāĻŋāĻŦāĻžāϰā§āϝāĻāĻžāĻŦā§ āϞā§āĻĄāĻŋāĻ āĻāĻŦāĻ āϤā§āϰā§āĻāĻŋāϰ āĻ
āĻŦāϏā§āĻĨāĻž āĻāĻĄāĻŧāĻŋāϤ - defineAsyncComponent()
āĻāύā§āύāϤ āĻŦāĻŋāĻāϞā§āĻĒāĻā§āϞāĻŋāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻāĻ āĻ
āĻŦāϏā§āĻĨāĻžāĻā§āϞāĻŋ āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻāϰāϤ⧠āϏāĻŽāϰā§āĻĨāύ āĻāϰā§:
js
const AsyncComp = defineAsyncComponent({
// the loader function
loader: () => import('./Foo.vue'),
// A component to use while the async component is loading
loadingComponent: LoadingComponent,
// Delay before showing the loading component. Default: 200ms.
delay: 200,
// A component to use if the load fails
errorComponent: ErrorComponent,
// The error component will be displayed if a timeout is
// provided and exceeded. Default: Infinity.
timeout: 3000
})
āϝāĻĻāĻŋ āĻāĻāĻāĻŋ āϞā§āĻĄāĻŋāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĒā§āϰāĻĻāĻžāύ āĻāϰāĻž āĻšāϝāĻŧ, āĻāĻāĻŋ āĻĒā§āϰāĻĨāĻŽā§ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻŦā§ āϝāĻāύ āĻāĻŋāϤāϰā§āϰ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻāĻŋ āϞā§āĻĄ āĻšāĻā§āĻā§ā§ˇ āϞā§āĻĄāĻŋāĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĻā§āĻāĻžāύā§āϰ āĻāĻā§ āĻāĻāĻāĻŋ āĻĄāĻŋāĻĢāϞā§āĻ 200ms āĻŦāĻŋāϞāĻŽā§āĻŦ āĻāĻā§ - āĻāϰ āĻāĻžāϰāĻŖ āĻšāϞ āĻĻā§āϰā§āϤ āύā§āĻāĻāϝāĻŧāĻžāϰā§āĻāĻā§āϞāĻŋāϤā§, āĻāĻāĻāĻŋ āϤāĻžāϤā§āĻā§āώāĻŖāĻŋāĻ āϞā§āĻĄāĻŋāĻ āĻ āĻŦāϏā§āĻĨāĻž āĻā§āĻŦ āĻĻā§āϰā§āϤ āĻĒā§āϰāϤāĻŋāϏā§āĻĨāĻžāĻĒāĻŋāϤ āĻšāϤ⧠āĻĒāĻžāϰ⧠āĻāĻŦāĻ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻāĻžāĻāĻā§āύāĻŋāϰ āĻŽāϤ⧠āĻĻā§āĻāĻžāϝāĻŧāĨ¤
āϝāĻĻāĻŋ āĻāĻāĻāĻŋ āϤā§āϰā§āĻāĻŋ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻĒā§āϰāĻĻāĻžāύ āĻāϰāĻž āĻšāϝāĻŧ, āĻāĻāĻŋ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻŦā§ āϝāĻāύ āϞā§āĻĄāĻžāϰ āĻĢāĻžāĻāĻļāύ āĻĻā§āĻŦāĻžāϰāĻž āĻĒā§āϰāϤā§āϝāĻžāĻŦāϰā§āϤāĻŋāϤ āĻĒā§āϰāϤāĻŋāĻļā§āϰā§āϤāĻŋ āĻĒā§āϰāϤā§āϝāĻžāĻā§āϝāĻžāύ āĻāϰāĻž āĻšāϝāĻŧāĨ¤ āϰāĻŋāĻā§ā§ā§āϏā§āĻ āĻāĻŋ āĻā§āĻŦ āĻŦā§āĻļāĻŋ āϏāĻŽāϝāĻŧ āύāĻŋāϞ⧠āĻāĻĒāύāĻŋ āϤā§āϰā§āĻāĻŋ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻāĻŋ āĻĻā§āĻāĻžāύā§āϰ āĻāύā§āϝ āĻāĻāĻāĻŋ āϏāĻŽāϝāĻŧāϏā§āĻŽāĻž āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤
Lazy Hydration â
āĻāĻ āĻŦāĻŋāĻāĻžāĻāĻāĻŋ āĻļā§āϧā§āĻŽāĻžāϤā§āϰ āϤāĻāύāĻ āĻĒā§āϰāϝā§āĻā§āϝ āϝāĻāύ āĻāĻĒāύāĻŋ āϏāĻžāϰā§āĻāĻžāϰ-āϏāĻžāĻāĻĄ āϰā§āύā§āĻĄāĻžāϰāĻŋāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻā§āύāĨ¤
Vue 3.5+ āĻ, āĻ ā§āϝāĻžāϏāĻŋāĻā§āĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞāĻŋ āĻšāĻžāĻāĻĄā§āϰā§āĻļāύ āĻā§āĻļāϞ āĻĒā§āϰāĻĻāĻžāύ āĻāϰ⧠āĻšāĻžāĻāĻĄā§āϰā§āĻā§āĻĄ āĻšāϞ⧠āύāĻŋāϝāĻŧāύā§āϤā§āϰāĻŖ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
Vue āĻŦāĻŋāϞā§āĻ-āĻāύ āĻšāĻžāĻāĻĄā§āϰā§āĻļāύ āĻā§āĻļāϞāĻā§āϞāĻŋāϰ āĻāĻāĻāĻŋ āϏāĻāĻā§āϝāĻž āĻĒā§āϰāĻĻāĻžāύ āĻāϰā§āĨ¤ āĻāĻ āĻ āύā§āϤāϰā§āύāĻŋāϰā§āĻŽāĻŋāϤ āĻā§āĻļāϞāĻā§āϞāĻŋ āĻĒā§āĻĨāĻāĻāĻžāĻŦā§ āĻāĻŽāĻĻāĻžāύāĻŋ āĻāϰāĻž āĻĒā§āϰāϝāĻŧā§āĻāύ āϝāĻžāϤ⧠āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻāϰāĻž āĻšāϞ⧠āϏā§āĻā§āϞāĻŋ āĻāĻžāĻ-āĻāĻžāĻāĻĒāĻžāύ⧠āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤
āύāĻāĻļāĻžāĻāĻŋ āĻāĻā§āĻāĻžāĻā§āϤāĻāĻžāĻŦā§ āĻĢā§āϞā§āĻā§āϏāĻŋāĻŦāϞāϰ āĻāύā§āϝ āύāĻŋāĻŽā§āύ-āϏā§āϤāϰā§āϰāĨ¤ āĻāĻŽā§āĻĒāĻžāĻāϞāĻžāϰ āϏāĻŋāύāĻā§āϝāĻžāĻā§āϏ āϏā§āĻāĻžāϰ āϏāĻŽā§āĻāĻžāĻŦā§āϝāĻāĻžāĻŦā§ āĻāĻāĻŋāϰ āĻāĻĒāϰ⧠āĻāĻŦāĻŋāώā§āϝāϤ⧠āĻŽā§āϞ āĻŦāĻž āĻāĻā§āĻ āϏā§āϤāϰā§āϰ āϏāĻŽāĻžāϧāĻžāύāĻā§āϞāĻŋāϤ⧠āϤā§āϰāĻŋ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰ⧠(āϝā§āĻŽāύ Nuxt)āĨ¤
Hydrate on Idle â
Hydrates via requestIdleCallback
:
js
import { defineAsyncComponent, hydrateOnIdle } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnIdle(/* optionally pass a max timeout */)
})
Hydrate on Visible â
āϝāĻāύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻ(āĻā§āϞāĻŋ) IntersectionObserver
āĻāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āĻĻā§āĻļā§āϝāĻŽāĻžāύ āĻšāϝāĻŧ āϤāĻāύ āĻšāĻžāĻāĻĄā§āϰā§āĻ āĻāϰā§āύ⧎
js
import { defineAsyncComponent, hydrateOnVisible } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
})
āĻĒāϰā§āϝāĻŦā§āĻā§āώāĻā§āϰ āĻāύā§āϝ āĻāĻā§āĻāĻŋāĻāĻāĻžāĻŦā§ āĻāĻāĻāĻŋ āĻŦāĻŋāĻāϞā§āĻĒ āĻ āĻŦāĻā§āĻā§āĻ āĻŽāĻžāύ āĻĒāĻžāϏ āĻāϰāϤ⧠āĻĒāĻžāϰā§:
js
hydrateOnVisible({ rootMargin: '100px' })
Hydrate on Media Query â
āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻŽāĻŋāĻĄāĻŋāϝāĻŧāĻž āĻā§āϝā§āϝāĻŧāĻžāϰ⧠āĻŽāĻŋāϞ⧠āĻā§āϞ⧠āĻšāĻžāĻāĻĄā§āϰā§āĻ āĻāϰā§āĨ¤
js
import { defineAsyncComponent, hydrateOnMediaQuery } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnMediaQuery('(max-width:500px)')
})
Hydrate on Interaction â
āĻāĻŽā§āĻĒā§āύā§āύā§āĻ āĻāϞāĻŋāĻŽā§āύā§āĻā§ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻāύāĻž(āĻā§āϞāĻŋ) āĻā§āϰāĻŋāĻāĻžāϰ āĻšāϞ⧠āĻšāĻžāĻāĻĄā§āϰā§āĻ āĻšāϝāĻŧāĨ¤ āϝ⧠āĻāĻā§āύā§āĻāĻāĻŋ āĻšāĻžāĻāĻĄā§āϰā§āĻļāύāĻā§ āĻā§āϰāĻŋāĻāĻžāϰ āĻāϰā§āĻā§ āϤāĻž āĻšāĻžāĻāĻĄā§āϰā§āĻļāύ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻšāϞ⧠āĻĒā§āύāϰāĻžāϝāĻŧ āĻĒā§āϞ⧠āĻāϰāĻž āĻšāĻŦā§āĨ¤
js
import { defineAsyncComponent, hydrateOnInteraction } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnInteraction('click')
})
āĻāĻāĻžāϧāĻŋāĻ āĻāĻā§āύā§āĻ āĻĒā§āϰāĻāĻžāϰā§āϰ āĻāĻāĻāĻŋ āϤāĻžāϞāĻŋāĻāĻžāĻ āĻšāϤ⧠āĻĒāĻžāϰā§:
js
hydrateOnInteraction(['wheel', 'mouseover'])
Custom Strategy â
ts
import { defineAsyncComponent, type HydrationStrategy } from 'vue'
const myStrategy: HydrationStrategy = (hydrate, forEachElement) => {
// forEachElement is a helper to iterate through all the root elements
// in the component's non-hydrated DOM, since the root can be a fragment
// instead of a single element
forEachElement(el => {
// ...
})
// call `hydrate` when ready
hydrate()
return () => {
// return a teardown function if needed
}
}
const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: myStrategy
})
Using with Suspense â
Async āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞāĻŋ <Suspense>
āĻŦāĻŋāϞā§āĻ-āĻāύ āĻāĻŽā§āĻĒā§āύā§āύā§āĻā§āϰ āϏāĻžāĻĨā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āϝā§āϤ⧠āĻĒāĻžāϰā§āĨ¤ <Suspense>
āĻāĻŦāĻ āĻ
ā§āϝāĻžāϏāĻŋāĻā§āĻ āĻāĻŽā§āĻĒā§āύā§āύā§āĻāĻā§āϞāĻŋāϰ āĻŽāϧā§āϝ⧠āĻŽāĻŋāĻĨāϏā§āĻā§āϰāĻŋāϝāĻŧāĻž āύāĻĨāĻŋāĻā§āĻā§āϤ āĻāϰāĻž āĻšāϝāĻŧā§āĻā§ <Suspense>
-āĻāϰ āĻāύā§āϝ āύāĻŋāĻŦā§āĻĻāĻŋāϤ āĻ
āϧā§āϝāĻžāϝāĻŧā§āĨ¤
GitHub-āĻ āĻāĻ āĻĒā§āώā§āĻ āĻžāĻāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ