Звичайний імпорт компонента потрапляє в головний бандл: навіть якщо важкий редактор чи графік відкриють раз на тиждень, його код завантажується з кожною сторінкою.
defineAsyncComponent завантажує компонент при першому рендері:
import { defineAsyncComponent } from 'vue'
const ChartPanel = defineAsyncComponent(() => import('./ChartPanel.vue'))
<button @click="showChart = true">Показати графік</button>
<ChartPanel v-if="showChart" :data="sales" />
Динамічний import() змушує збирач винести компонент і його залежності (бібліотеку графіків) в окремий файл. Він завантажиться, лише коли showChart стане true.
Стани завантаження й помилки:
const ChartPanel = defineAsyncComponent({
loader: () => import('./ChartPanel.vue'),
loadingComponent: Spinner,
delay: 200, // показати спінер лише якщо завантаження довше 200 мс
errorComponent: LoadError,
timeout: 10000, // вважати помилкою після 10 с
})
delay за замовчуванням 200 мс - щоб на швидкому з'єднанні спінер не «блимав».
Де застосовувати:
- модальні вікна, редактори тексту, карти, графіки, PDF-переглядачі;
- вкладки, які відкривають рідко;
- компоненти для певних ролей (адмінські панелі всередині звичайної сторінки).
Сторінки маршрутизатора розділяють так само, але простіше - Vue Router приймає функцію з import() прямо в маршруті.
Що варто знати:
- асинхронний компонент приймає ті самі props, слоти й події, що й звичайний - для батька різниці немає;
- не дробити надто дрібно: десятки маленьких частин - десятки запитів. Виносять важке й рідко потрібне;
- помилки після деплою: у давно відкритій вкладці стара частина може зникнути з сервера -
errorComponentз пропозицією оновити сторінку краще за порожнє місце; - у SSR асинхронні компоненти можна ще й гідрувати ліниво (Vue 3.5+).