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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs