Todos los artículos
Rendimiento· Intermedio

defineAsyncComponent en Vue 3: Implementación y casos de uso.

Carga componentes bajo demanda y muestra estados de carga y error con defineAsyncComponent.

LA

Luis Aldair Quispe Rios

3 min de lectura
split js files with defineAsyncComponent

Objetivo y requisitos

Con Vue 3 y Vite, vamos a descargar un componente cuando el usuario lo solicite y mostrar estados de carga y error. Crea los tres componentes auxiliares siguientes dentro de src/components. Los snippets de uso se colocan en src/App.vue.

Componentes auxiliares completos

AsyncComponent.vue:

<template><section><h2>Componente cargado</h2><p>Este contenido llegó bajo demanda.</p></section></template>

LoadingComponent.vue:

<template><p role="status">Cargando componente…</p></template>

ErrorComponent.vue:

<template><p role="alert">No pudimos cargar el componente. Comprueba tu conexión y recarga la página.</p></template>

Uso Básico:

Para definir un componente asíncrono, se utiliza defineAsyncComponent junto con una función que retorna una promesa. Generalmente, se emplea la función de importación dinámica para cargar el componente:

<script setup lang="ts">
  import { defineAsyncComponent } from 'vue'

  const AsyncComponent = defineAsyncComponent(() =>
    import('./components/AsyncComponent.vue')
  )
</script>

En este ejemplo, AsyncComponent se cargará solo cuando sea necesario, reduciendo el tamaño inicial del paquete de la aplicación.

Manejo de Estados de Carga y Error:

defineAsyncComponent también permite manejar estados de carga y error mediante una configuración adicional:

<script setup lang="ts">
  import { defineAsyncComponent, ref } from 'vue'
  import LoadingComponent from './components/LoadingComponent.vue'
  import ErrorComponent from './components/ErrorComponent.vue'

  const AsyncComponent = defineAsyncComponent({
    loader: () => import('./components/AsyncComponent.vue'),
    loadingComponent: LoadingComponent,
    errorComponent: ErrorComponent,
    delay: 200, // 200ms default
    timeout: 3000, // Infinity default
  })
</script>
  • loader: Función que retorna la promesa del componente a cargar.

  • loadingComponent: Componente que se muestra mientras el componente asíncrono se está cargando.

  • errorComponent: Componente que se muestra si ocurre un error durante la carga.

  • delay: Tiempo en milisegundos antes de mostrar el componente de carga.

  • timeout: Tiempo máximo en milisegundos para intentar cargar el componente antes de mostrar el componente de error.

Casos de Uso:

  1. Carga bajo demanda: Cargar componentes solo cuando el usuario los necesita, como en rutas específicas o modales, mejorando el rendimiento inicial de la aplicación.

  2. División de código: Dividir la aplicación en fragmentos más pequeños que se cargan según sea necesario, lo que reduce el tamaño del paquete inicial y mejora los tiempos de carga.

  3. Manejo de componentes pesados: Cargar componentes que dependen de bibliotecas grandes o que tienen un impacto significativo en el rendimiento solo cuando son necesarios.

Ejemplo completo:

<script setup lang="ts">
  import { defineAsyncComponent, ref } from 'vue'
  import LoadingComponent from './components/LoadingComponent.vue'
  import ErrorComponent from './components/ErrorComponent.vue'

  const showAsyncComponent = ref(false)

  const AsyncComponent = defineAsyncComponent({
    loader: () => import('./components/AsyncComponent.vue'),
    loadingComponent: LoadingComponent,
    errorComponent: ErrorComponent,
    delay: 200, // 200ms default
    timeout: 3000, // Infinity default
  })
</script>

<template>
  <main>
    <div class="flex items-center justify-center mb-4">
      <button
        @click="showAsyncComponent = !showAsyncComponent"
        class="px-4 py-2 cursor-pointer bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75"
      >
        Cargar componente async
      </button>
    </div>

    <AsyncComponent v-if="showAsyncComponent" />
  </main>
</template>

Conclusión:

defineAsyncComponent es una herramienta poderosa en Vue 3 para optimizar aplicaciones grandes, permitiendo una carga más eficiente de componentes y mejorando la experiencia del usuario al reducir los tiempos de carga iniciales.

Comprueba el resultado

Ejecuta npm run build y npm run preview. Con la caché desactivada y la red ralentizada en Network, pulsa el botón: verás la descarga del fragmento y, si supera el delay, el mensaje de carga. Bloquea el fragmento antes de pulsar para comprobar el mensaje de error. En una conexión rápida, el estado de carga puede no llegar a verse.

Errores frecuentes

v-if decide cuándo montar el componente; defineAsyncComponent por sí solo no retrasa un componente que ya se renderiza en la pantalla inicial. Después de cargarlo, el módulo se reutiliza. El timeout muestra el estado de error, pero no cancela automáticamente una descarga en curso. No promete una mejora medible en todas las aplicaciones: compara el tamaño inicial y el tiempo de interacción.

Para rutas de Vue Router usa la función de importación dinámica directamente en la definición de la ruta; reserva defineAsyncComponent para componentes. Consulta componentes asíncronos de Vue y carga diferida de rutas.

Ejemplo de carga asíncrona de componentes en Vue.js usando defineAsyncComponent, mostrando un componente en estado de carga con un spinner y código JavaScript para importar dinámicamente componentes.
Ejemplo de carga asíncrona de componentes en Vue.js usando defineAsyncComponent, mostrando un componente en estado de carga con un spinner y código JavaScript para importar dinámicamente componentes.

Sigue leyendo

Cómo usar v-memo en Vue 3: dependencias y medición de rendimiento

Cómo usar v-memo en Vue 3: dependencias y medición de rendimiento

Optimiza una lista con v-memo, elige dependencias completas y compara el resultado antes de adoptarlo.
defineModel() en Vue 3.4+: La evolución elegante del v-model en componentes

defineModel() en Vue 3.4+: La evolución elegante del v-model en componentes

Crea un input reutilizable con defineModel y aplica un modificador personalizado sin duplicar el modelo.
¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

¿Cómo integrar Tailwind 4 en Vue.js 3 + Vite?

Configura Tailwind CSS 4 en Vue 3 con los plugins de Vue y Tailwind para Vite.