JAVASCRIPT
Lazy Loading (Async) Components in Vue 3 for Performance
Improve your Vue 3 application's performance by lazy loading components using `defineAsyncComponent`, splitting your bundle and reducing initial load times.
// main.js (no special changes needed, standard Vue app setup)
import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
// components/HeavyComponent.vue (A component that might be large or not immediately needed)
<template>
<div class="heavy-component">
<h3>Heavy Component Loaded!</h3>
<p>This component's code was only loaded when it was needed.</p>
<img src="https://via.placeholder.com/150/FF0000/FFFFFF?text=Heavy+Image" alt="Heavy placeholder image" />
<p>It can contain complex logic, large third-party libraries, or many child components.</p>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('HeavyComponent mounted and its code has just arrived!');
});
</script>
<style scoped>
.heavy-component {
border: 2px solid #42b983;
padding: 20px;
margin: 20px 0;
background-color: #e6fff0;
border-radius: 8px;
text-align: center;
}
img {
max-width: 100%;
height: auto;
margin-top: 15px;
}
</style>
// App.vue (Implementing lazy loading)
<template>
<div class="app-container">
<h1>Vue 3 Lazy Loading Example</h1>
<p>This content loads immediately.</p>
<button @click="loadComponent = !loadComponent">
{{ loadComponent ? 'Unload' : 'Load' }} Heavy Component
</button>
<p v-if="!loadComponent" class="loading-message">Click the button to load the Heavy Component dynamically.</p>
<template v-if="loadComponent">
<Suspense>
<template #fallback>
<div class="loading-state">
Loading HeavyComponent... Please wait.
<div class="spinner"></div>
</div>
</template>
<HeavyComponentAsync />
</Suspense>
</template>
<p>More application content below (always loaded).</p>
</div>
</template>
<script setup>
import { ref, defineAsyncComponent } from 'vue';
const loadComponent = ref(false);
const HeavyComponentAsync = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
.then(module => module.default)
.catch(error => {
console.error('Failed to load HeavyComponent:', error);
// return import('./components/ErrorFallback.vue'); // Optional: Fallback component on error
})
);
</script>
<style>
.app-container {
max-width: 900px;
margin: 50px auto;
font-family: Arial, sans-serif;
text-align: center;
}
button {
padding: 10px 20px;
font-size: 1em;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
}
button:hover {
background-color: #0056b3;
}
.loading-message {
margin-top: 20px;
font-style: italic;
color: #666;
}
.loading-state {
border: 1px dashed #ccc;
padding: 20px;
margin: 20px 0;
background-color: #f9f9f9;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100px;
font-weight: bold;
color: #333;
}
.spinner {
border: 4px solid rgba(0, 0, 0, 0.1);
width: 30px;
height: 30px;
border-radius: 50%;
border-left-color: #09f;
animation: spin 1s ease infinite;
margin-top: 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
How it works: This snippet demonstrates how to implement lazy loading (also known as code splitting or async components) in Vue 3 using `defineAsyncComponent`. Instead of bundling all component code into the initial JavaScript payload, `defineAsyncComponent` allows you to load components only when they are actually needed, such as when a user interacts with a certain UI element or navigates to a specific route. This significantly reduces initial load times and improves application performance. The `Suspense` component is used to provide a fallback loading state while the async component is being fetched, offering a better user experience.