JAVASCRIPT
Lazy Loading Components with Vue 3 `defineAsyncComponent`
Optimize Vue 3 application performance by using `defineAsyncComponent` to lazy load components, reducing initial bundle size and improving load times.
// components/HeavyComponent.vue
<template>
<div class="heavy-component">
<h3>This is a Heavy/Complex Component</h3>
<p>Imagine this component contains a lot of logic, data, or large third-party libraries.</p>
<p>Loading it asynchronously helps improve initial page load performance.</p>
<p>Generated at: {{ new Date().toLocaleTimeString() }}</p>
</div>
</template>
<script setup>
// Simulate a delay for demonstration purposes
const delay = ms => new Promise(res => setTimeout(res, ms));
await delay(1000); // Simulate network or processing delay
</script>
<style scoped>
.heavy-component {
background-color: #f0f0f0;
border: 1px solid #ddd;
padding: 20px;
margin-top: 20px;
border-radius: 8px;
}
</style>
<!-- App.vue (example usage) -->
<template>
<div>
<h1>Async Component Example</h1>
<p>Content before the async component.</p>
<button @click="loadComponent = true" :disabled="loadComponent">
{{ loadComponent ? 'Component Loading...' : 'Load Async Component' }}
</button>
<Suspense v-if="loadComponent">
<!-- Main content for async component -->
<HeavyComponent />
<!-- Loading state via fallback slot -->
<template #fallback>
<div class="loading-state">
<p>Loading Heavy Component...</p>
<div class="spinner"></div>
</div>
</template>
</Suspense>
<p>Content after the async component.</p>
</div>
</template>
<script setup>
import { ref, defineAsyncComponent } from 'vue';
const loadComponent = ref(false);
// Define the async component
const HeavyComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
);
// With options for error handling, loading state, and timeout:
// const HeavyComponent = defineAsyncComponent({
// loader: () => import('./components/HeavyComponent.vue'),
// loadingComponent: {
// template: '<div class="loading-state"><p>Loading...</p><div class="spinner"></div></div>'
// },
// errorComponent: {
// template: '<div class="error-state">Failed to load component!</div>'
// },
// delay: 200, // The delay before showing the loading component (ms)
// timeout: 3000 // Error if loading takes longer than 3s (ms)
// });
</script>
<style>
.loading-state, .error-state {
padding: 15px;
border: 1px dashed #ccc;
margin-top: 20px;
text-align: center;
background-color: #f9f9f9;
}
.spinner {
border: 4px solid rgba(0, 0, 0, .1);
border-left-color: #42b983;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 10px auto;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
How it works: This snippet demonstrates using `defineAsyncComponent` to lazy load a component in Vue 3. This technique defers loading a component's code until it's actually needed, significantly reducing the initial JavaScript bundle size and improving application startup performance. It's often used in conjunction with the `<Suspense>` component to display a fallback loading state while the asynchronous component is being fetched and rendered.