Configurar Vite desde astro.config: la clave vite
La clave vite de astro.config es la puerta directa a la configuración del motor subyacente. Cómo usar resolve.alias para nombrar rutas de importación, el binomio ssr.external y ssr.noExternal para decidir qué dependencias se empaquetan en el servidor y cuáles quedan fuera, optimizeDeps para afinar el pre-empaquetado en desarrollo, y plugins para extender la tubería cuando la configuración de alto nivel de Astro no llega.
La clave vite como válvula de escape
Cuando escribes una clave vite en astro.config, no reemplazas la configuración de Vite: la fusionas con la que Astro ya genera. Astro configura por debajo su plugin del compilador, los ajustes de SSR según tu adapter y decenas de detalles que no deberías tocar. Tu objeto vite se mezcla encima, añadiendo o ajustando lo que necesites sin desmontar lo anterior. Por eso conviene tratarla con respeto: es potente porque es directa, y directa significa sin red.
import { defineConfig } from 'astro/config';export default defineConfig({ vite: { resolve: { alias: { '@lib': '/src/lib', '@ui': '/src/components/ui' }, }, ssr: { noExternal: ['paquete-solo-esm'], external: ['dependencia-con-binario-nativo'], }, optimizeDeps: { include: ['libreria-cjs-profunda'], }, plugins: [], },});resolve.alias: nombrar rutas
La primera necesidad honesta que suele empujarte a vite es dejar de escribir importaciones relativas frágiles. Un import que sube cuatro carpetas con puntos y barras es ilegible y se rompe en cuanto mueves el fichero. Con resolve.alias das un nombre estable a una carpeta y el motor lo resuelve por ti en todas partes.
export default defineConfig({ vite: { resolve: { alias: { '@components': '/src/components', '@lib': '/src/lib', '@styles': '/src/styles', }, }, },});Con esto, import Boton from '@components/Boton.astro' funciona desde cualquier profundidad del proyecto. Un matiz importante: el alias lo resuelve Vite en tiempo de build, pero tu editor y el chequeo de tipos leen tsconfig.json. Para que ambos coincidan conviene declarar los mismos nombres en la clave paths de tsconfig.json.
// tsconfig.json: los mismos alias, para que el editor los entienda{ "compilerOptions": { "baseUrl": ".", "paths": { "@components/*": ["src/components/*"], "@lib/*": ["src/lib/*"] } }}La regla es mantener las dos listas sincronizadas: Vite resuelve el build, tsconfig alimenta al editor. Cuando divergen aparece el desconcierto clásico de un import que compila pero el editor subraya en rojo, o al revés, un import que el editor acepta y el build no encuentra.
ssr.external y noExternal: qué se empaqueta para el servidor
Aquí vive el ajuste más sutil y más útil de todos. Cuando construyes para SSR, Vite debe decidir, dependencia a dependencia, si la empaqueta dentro del bundle del servidor o la deja externa —es decir, la importa en tiempo de ejecución desde node_modules como haría Node—. Por defecto, Vite externaliza las dependencias de Node: no las empaqueta, confía en que estén instaladas en el servidor. Esa política acierta casi siempre, pero falla en dos casos opuestos, y para cada uno hay una clave.
El caso típico de noExternal es una librería que asume que alguien la va a empaquetar y no funciona si se importa cruda en el servidor —frecuente en paquetes de estilos o de componentes—. El caso típico de external es un módulo con un binario nativo compilado que el bundler no puede ni debe procesar. Cuando un despliegue de SSR falla con un error de módulo que no se encuentra o de sintaxis inesperada al arrancar el servidor, la causa suele estar en esta frontera, y la cura es mover el paquete conflictivo a la lista correcta.
Una advertencia sobre el runtime de destino: qué debe externalizarse depende de dónde se ejecute el servidor. Un adapter de Node puede dejar externas las dependencias porque estarán instaladas junto al servidor; un adapter de edge, sin node_modules en tiempo de ejecución, obliga a empaquetar mucho más dentro del propio bundle. El mismo proyecto puede necesitar listas distintas según a dónde lo despliegues, y por eso conviene tratar estas claves como parte de la configuración de despliegue, no como un ajuste universal.
optimizeDeps y plugins: pre-empaquetado y extensión
optimizeDeps gobierna el pre-empaquetado de dependencias del dev server, esa fase previa que convierte a ESM y colapsa los ficheros de cada librería. Casi siempre acierta sola, pero tiene dos escotillas. Con optimizeDeps.include fuerzas a pre-empaquetar una dependencia que Vite no detectó —típico cuando una librería esconde sus imports tras CommonJS profundo—. Con optimizeDeps.exclude la excluyes, útil para un paquete que debe servirse sin tocar.
export default defineConfig({ vite: { optimizeDeps: { include: ['libreria-con-imports-cjs-ocultos'], exclude: ['paquete-que-sirve-su-propio-esm'], }, },});La clave plugins cierra el círculo: es donde enchufas plugins de Vite o de la API de Rollup que Rolldown mantiene compatible. Antes de escribir uno, recuerda que Astro extiende sus capacidades por integrations, no por plugins sueltos; baja a vite.plugins solo cuando necesitas un plugin del ecosistema que no viene envuelto en una integración de Astro.
Los usos legítimos de vite.plugins en un proyecto Astro suelen ser contados y reconocibles:
- Un visualizador de bundle para auditar tamaños, que verás en la lección de diagnóstico.
- Un plugin que transforma un formato de fichero que Astro no maneja de fábrica.
- Un plugin de inspección o depuración que quieres activo solo durante el desarrollo.