Back

Cómo Crear y Usar Plugins en Vite

Cómo Crear y Usar Plugins en Vite

Crear plugins de Vite personalizados te permite extender tu proceso de compilación más allá de la configuración predeterminada—ya sea que necesites transformar tipos de archivos personalizados, inyectar lógica en tiempo de compilación o agregar middleware al servidor de desarrollo. Si has alcanzado los límites de la configuración estándar de Vite, crear tu propio plugin es el siguiente paso natural.

Esta guía cubre los conceptos esenciales: cómo funciona la API de Plugins de Vite, los hooks de ciclo de vida clave que utilizarás y ejemplos prácticos para comenzar. Aprenderás a crear, probar y publicar plugins que resuelven problemas del mundo real en tu flujo de trabajo de desarrollo.

Puntos Clave

  • Los plugins de Vite extienden tanto los procesos de desarrollo como de compilación de producción a través de hooks de ciclo de vida
  • La mayoría de los plugins de Rollup funcionan en Vite, pero las funcionalidades del servidor de desarrollo requieren hooks específicos de Vite
  • Comienza con transformaciones simples antes de avanzar a patrones más complejos como módulos virtuales
  • Sigue las convenciones de nomenclatura y estándares de documentación al publicar plugins

Entendiendo los Plugins de Vite y su Relación con Rollup

Los plugins de Vite son objetos JavaScript que se conectan a diferentes etapas del proceso de desarrollo y compilación. Están construidos sobre el sistema de plugins de Rollup, con hooks adicionales específicos para el servidor de desarrollo de Vite.

Vite utiliza dos herramientas de compilación diferentes internamente: esbuild impulsa el servidor de desarrollo ultrarrápido con módulos ES nativos, mientras que Rollup maneja el empaquetado de producción para una salida óptima. Esta arquitectura dual significa que tus plugins pueden dirigirse a entornos específicos usando la opción apply:

function myPlugin(): Plugin {
  return {
    name: 'my-plugin',
    apply: 'serve', // Solo se ejecuta durante el desarrollo
    // ... hooks
  }
}

La mayoría de los plugins de Rollup funcionan en Vite sin modificaciones. Sin embargo, si necesitas funcionalidad del servidor de desarrollo—como agregar middleware o modificar HTML durante el desarrollo—necesitarás hooks específicos de Vite.

Estructura Básica y Configuración de Plugins

Todo plugin de Vite debe tener una propiedad name y al menos una función hook:

import type { Plugin } from 'vite'

function myPlugin(options?: MyPluginOptions): Plugin {
  return {
    name: 'vite-plugin-example',
    enforce: 'pre', // Opcional: controla el orden de los plugins
    apply: 'build', // Opcional: 'serve' | 'build' | undefined
    
    // Las funciones hook van aquí
    transform(code, id) {
      if (id.endsWith('.custom')) {
        return transformCustomFile(code)
      }
    }
  }
}

La API de Plugins proporciona definiciones de TypeScript para todos los hooks y opciones. Importa el tipo Plugin desde ‘vite’ para obtener seguridad de tipos completa y autocompletado.

Hooks de Ciclo de Vida Esenciales en la API de Plugins

Diferentes hooks se activan en diferentes etapas del proceso de compilación. Estos son los más utilizados:

Hooks de Configuración

  • config: Modifica la configuración de Vite antes de que se resuelva
  • configResolved: Accede a la configuración final resuelta

Hooks de Transformación

  • transform: Modifica el código fuente de módulos individuales
  • load: Lógica de carga personalizada para tipos de archivos específicos
  • resolveId: Resolución de módulos personalizada
{
  name: 'transform-plugin',
  transform(code, id) {
    if (!id.includes('node_modules') && id.endsWith('.js')) {
      return {
        code: addCustomHeader(code),
        map: null // Soporte para source maps
      }
    }
  }
}

Hooks de Servidor y Compilación

  • configureServer: Agrega middleware personalizado al servidor de desarrollo
  • transformIndexHtml: Modifica archivos HTML
  • writeBundle: Se ejecuta después de que el bundle se escribe en disco

Cada hook tiene tipos de retorno y tiempos de ejecución específicos. El hook transform se ejecuta para cada módulo, así que mantenlo rápido. Usa load para operaciones costosas en archivos específicos.

Construyendo tu Primer Plugin de Vite: Ejemplos Prácticos

Construyamos tres plugins prácticos que demuestran patrones comunes:

Ejemplo 1: Modificación de HTML

function htmlPlugin(): Plugin {
  return {
    name: 'html-modifier',
    transformIndexHtml(html) {
      return html.replace(
        '</head>',
        '<script>console.log("Injected!")</script></head>'
      )
    }
  }
}

Ejemplo 2: Middleware del Servidor de Desarrollo

function analyticsPlugin(): Plugin {
  return {
    name: 'request-analytics',
    configureServer(server) {
      server.middlewares.use((req, res, next) => {
        console.log(`${req.method} ${req.url}`)
        next()
      })
    }
  }
}

Ejemplo 3: Generación de Archivos en Tiempo de Compilación

import path from 'path'
import fs from 'fs'
import type { Plugin, ResolvedConfig } from 'vite'

function generateManifest(): Plugin {
  let config: ResolvedConfig
  
  return {
    name: 'generate-manifest',
    configResolved(resolvedConfig) {
      config = resolvedConfig
    },
    writeBundle() {
      const manifestPath = path.join(config.build.outDir, 'manifest.json')
      fs.writeFileSync(manifestPath, JSON.stringify({
        timestamp: Date.now(),
        version: process.env.npm_package_version
      }))
    }
  }
}

Para depuración, usa console.log en tus hooks para rastrear la ejecución. Los métodos this.warn() y this.error() proporcionan mejor reporte de errores que lanzar excepciones.

Patrones Avanzados de Plugins y Mejores Prácticas

Módulos Virtuales

Crea módulos que no existen en disco:

const virtualModuleId = 'virtual:my-module'
const resolvedVirtualModuleId = '\0' + virtualModuleId

export function virtualPlugin(): Plugin {
  return {
    name: 'virtual-plugin',
    resolveId(id) {
      if (id === virtualModuleId) {
        return resolvedVirtualModuleId
      }
    },
    load(id) {
      if (id === resolvedVirtualModuleId) {
        return `export const msg = "from virtual module"`
      }
    }
  }
}

Optimización de Rendimiento

Cachea transformaciones costosas:

const cache = new Map<string, string>()

function cachedTransform(): Plugin {
  return {
    name: 'cached-transform',
    transform(code, id) {
      if (cache.has(id)) return cache.get(id)
      
      const result = expensiveOperation(code)
      cache.set(id, result)
      return result
    }
  }
}

Prueba tus plugins de Vite usando Vitest con la API createServer para verificar el comportamiento de los hooks de forma aislada.

Publicando y Compartiendo tu Plugin

Sigue estas convenciones al publicar:

  1. Nombra tu paquete vite-plugin-[nombre]
  2. Incluye "vite-plugin" en las keywords de package.json
  3. Documenta por qué es específico de Vite (si usa hooks exclusivos de Vite)
  4. Agrega prefijos de framework si es específico de un framework: vite-plugin-vue-[nombre]

Crea un README claro con instrucciones de instalación, ejemplos de configuración y documentación de la API. Envía tu plugin a awesome-vite para llegar a la comunidad.

Conclusión

Crear plugins de Vite personalizados te da control completo sobre tu proceso de compilación. Comienza con transformaciones simples usando hooks como transform o transformIndexHtml, luego expande a patrones más complejos según sea necesario. La API de Plugins es poderosa pero accesible—la mayoría de los plugins requieren solo unos pocos hooks para resolver problemas específicos.

Para una exploración más profunda, consulta la documentación oficial de plugins de Vite y estudia plugins populares en el ecosistema. Tu próxima optimización de compilación o mejora de flujo de trabajo podría estar a solo un plugin de distancia.

Preguntas Frecuentes

Sí, la mayoría de los plugins de Rollup funcionan con Vite sin modificaciones. Sin embargo, los plugins que dependen del hook moduleParsed o necesitan funcionalidad del servidor de desarrollo requieren adaptaciones específicas de Vite. Consulta la documentación del plugin para notas de compatibilidad con Vite.

Usa declaraciones console.log en tus hooks para rastrear el flujo de ejecución. Los métodos this.warn() y this.error() proporcionan mejor reporte de errores. También puedes usar la variable de entorno DEBUG con Vite para ver logs detallados.

La opción enforce controla el orden de ejecución de los plugins. Los plugins pre se ejecutan antes de los plugins principales de Vite, los plugins post se ejecutan después. Usa pre para transformaciones de entrada y post para modificaciones de salida. Sin enforce, los plugins se ejecutan en el orden en que aparecen.

Considera publicar si tu plugin resuelve un problema que otros podrían enfrentar, incluso si es especializado. Documenta claramente su caso de uso específico. Para plugins verdaderamente específicos de un proyecto, mantenlos locales o en un registro privado en su lugar.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay