JAVASCRIPT
Vue 3 Lazy Loading Components with `defineAsyncComponent`
Optimize your Vue 3 application's performance and initial load time by dynamically importing components only when they are needed, using `defineAsyncComponent`.
// src/views/HomeView.vue
<template>
<div class="home-view">
<h1>Welcome to the Home Page</h1>
<p>This content loads immediately.</p>
<button @click="showModal = true">Load & Show Modal</button>
<div v-if="showModal">
<!-- The AsyncModal component will only be loaded when `showModal` is true -->
<AsyncModal @close="showModal = false" />
</div>
<button @click="loadAnalytics = true">Load Analytics Widget</button>
<div v-if="loadAnalytics">
<AsyncAnalyticsWidget />
</div>
<h2>Other Content</h2>
<p>More static content...</p>
</div>
</template>
<script setup>
import { ref, defineAsyncComponent } from 'vue';
// Basic async component definition
const AsyncModal = defineAsyncComponent(() => import('../components/LazyModal.vue'));
// More advanced async component with loading, error, and delay options
const AsyncAnalyticsWidget = defineAsyncComponent({
loader: () => import('../components/LazyAnalyticsWidget.vue'),
loadingComponent: () => import('../components/LoadingSpinner.vue'), // Component to show while loading
errorComponent: () => import('../components/ErrorFallback.vue'), // Component to show if load fails
delay: 200, // Delay in ms before showing the loading component. Default: 200ms.
timeout: 3000 // Timeout in ms after which the error component will be displayed. Default: Infinity.
});
const showModal = ref(false);
const loadAnalytics = ref(false);
</script>
<style scoped>
.home-view {
padding: 20px;
font-family: sans-serif;
}
button {
margin: 10px;
padding: 10px 15px;
cursor: pointer;
}
</style>
// src/components/LazyModal.vue
<template>
<div class="modal-backdrop" @click.self="$emit('close')">
<div class="modal-content">
<h3>Lazy Loaded Modal</h3>
<p>This modal content was loaded asynchronously.</p>
<button @click="$emit('close')">Close</button>
</div>
</div>
</template>
<script setup>
import { defineEmits } from 'vue';
defineEmits(['close']);
console.log('LazyModal component loaded!');
</script>
<style scoped>
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 500px;
text-align: center;
}
</style>
// src/components/LazyAnalyticsWidget.vue
<template>
<div class="analytics-widget">
<h4>Lazy Loaded Analytics Widget</h4>
<p>Data visualization for your performance metrics.</p>
<p>Loaded at: {{ new Date().toLocaleTimeString() }}</p>
</div>
</template>
<script setup>
console.log('LazyAnalyticsWidget component loaded!');
</script>
<style scoped>
.analytics-widget {
border: 1px solid #42b983;
padding: 15px;
margin-top: 20px;
border-radius: 5px;
background-color: #e6f7ed;
}
</style>
// src/components/LoadingSpinner.vue (example)
<template>
<div class="loading-spinner">Loading...</div>
</template>
<style scoped> .loading-spinner { color: #42b983; font-weight: bold; padding: 10px; } </style>
// src/components/ErrorFallback.vue (example)
<template>
<div class="error-fallback">Error loading component!</div>
</template>
<style scoped> .error-fallback { color: red; font-weight: bold; padding: 10px; border: 1px solid red; background-color: #ffe6e6; } </style>
How it works: This snippet demonstrates how to use Vue 3's `defineAsyncComponent` to lazy load components, improving initial page load performance. Instead of bundling all components into the main chunk, `defineAsyncComponent` creates a wrapper that only loads the target component's code when it's actually rendered. This example shows both a basic lazy load and an advanced setup with `loadingComponent`, `errorComponent`, `delay`, and `timeout` options to provide a better user experience during the loading process or in case of failure.