La transición histórica: de dos motores a Rolldown
Durante años Vite usó dos bundlers distintos: esbuild para pre-empaquetar y transformar en dev, Rollup para el bundle de producción. Dos motores elegidos por virtudes opuestas —velocidad frente a calidad de salida— pero con dos parsers y dos semánticas, y por tanto una fuente estructural de divergencias dev/build. Cómo Rolldown, en Rust y sobre Oxc, unifica ambos en Vite 8 y estrecha esa brecha.
La divergencia entre dev y build que viste en el nivel anterior no era solo conceptual: durante buena parte de la historia de Vite fue también física, porque cada naturaleza corría sobre un motor de bundler diferente. Dev se apoyaba en esbuild; build, en Rollup. Dos programas escritos en lenguajes distintos, con parsers distintos y semánticas sutilmente distintas, unidos por la interfaz común de Vite. Entender por qué se eligieron dos motores, qué fricción produjo esa dualidad, y cómo Rolldown la disuelve en Vite 8, es entender la última costura que separaba las dos mitades.
- Entender por qué Vite eligió dos motores: esbuild por velocidad, Rollup por calidad y plugins.
- Ver la fricción estructural de tener dos parsers y dos semánticas.
- Conocer Rolldown como bundler en Rust, compatible con la API de Rollup, sobre Oxc.
- Comprender cómo unificar el motor estrecha la brecha dev/build.
Para entender la unificación de Vite 8 hay que reconstruir primero por qué existían dos motores, qué costó tenerlos y qué hizo falta para fundirlos en uno. Es una historia de virtudes repartidas y de una interfaz lo bastante buena como para sobrevivir al reemplazo de todos sus motores por debajo.
Por qué dos motores
Cuando Vite nació, ningún bundler cumplía a la vez las dos exigencias. Para el dev server hacía falta velocidad bruta: pre-empaquetar dependencias y transpilar TypeScript y JSX en milisegundos, sin frenar la iteración. Esa corona la tenía esbuild, escrito en Go, órdenes de magnitud más rápido que cualquier alternativa en JavaScript, aunque su tree shaking y su control de la salida fueran más limitados.
Para el build de producción las prioridades se invertían. Ahí importaba la calidad del artefacto —el mejor tree shaking, un code splitting fino, un control exacto de los chunks— y, sobre todo, un ecosistema maduro de plugins. Esa corona la tenía Rollup, cuya API de plugins se había vuelto un estándar de facto. Vite tomó una decisión pragmática: usar cada motor donde brillaba. esbuild para pre-empaquetar y transformar en dev; Rollup para empaquetar en producción.
No fue una elección perezosa, sino la lectura correcta de un ecosistema en el que las virtudes estaban repartidas. esbuild demostró que un bundler en un lenguaje compilado podía ser cien veces más rápido; Rollup había definido, años antes, qué significaba un tree shaking serio sobre ESM y había cultivado la comunidad de plugins que todo el mundo reutilizaba. Vite no quiso renunciar a ninguna de las dos herencias, así que las cosió: la velocidad de una donde importa la iteración, la madurez de la otra donde importa el resultado.
El reparto de tareas era nítido:
- esbuild, en dev: pre-empaquetaba
node_modulesconoptimizeDepsy transpilaba cada módulo TS o JSX al vuelo. - esbuild, además: convertía CommonJS a ESM para que el navegador pudiera cargar dependencias antiguas sin ahogarse.
- Rollup, en build: resolvía el grafo completo, aplicaba el tree shaking y decidía el troceado en chunks.
- Rollup, también: ejecutaba la cadena de plugins que daba forma final al artefacto de producción.
esbuild en dev
En Go. Pre-empaquetaba dependencias con optimizeDeps y transpilaba TS y JSX a toda velocidad. Elegido por latencia, no por calidad de salida.
Rollup en build
En JavaScript. El mejor tree shaking, code splitting fino y una API de plugins convertida en estándar. Elegido por calidad y ecosistema.
El coste de la dualidad
La decisión fue acertada, pero no salió gratis. Dos motores significan dos parsers leyendo tu código, dos representaciones internas y dos conjuntos de reglas que no coinciden al cien por cien. esbuild y Rollup no interpretan idéntico cada rincón de la sintaxis, no aplican las mismas optimizaciones ni tratan igual ciertos casos límite. La documentación de Vite lo decía sin rodeos: en dev transformamos con esbuild, en build empaquetamos con Rollup, y ocasionalmente notarás diferencias.
Esa costura era la raíz material de muchos bugs “funcionaba en dev”. Un plugin que se comportaba distinto según la fase, una transformación que esbuild hacía de una manera y Rollup de otra, un helper inyectado con forma diferente: pequeñas discrepancias que solo se manifestaban al cruzar de un motor al otro. La brecha dev/build no era únicamente pereza frente a ansiedad, sino también Go frente a JavaScript, un AST frente a otro.
El ejemplo canónico eran los plugins. La API de plugins de Vite es un superconjunto de la de Rollup, pero en dev muchos hooks los ejecutaba Vite sobre esbuild, mientras que en build los ejecutaba Rollup de verdad. Un plugin que asumía la semántica exacta de uno podía fallar sutilmente bajo el otro, y depurar eso obligaba a razonar sobre dos pipelines a la vez. La complejidad no estaba en tu código, sino en la frontera entre dos motores que no eran el mismo.
Las divergencias tenían firmas reconocibles:
- Un hook de plugin que transformaba distinto según lo ejecutara Vite sobre esbuild o Rollup de verdad.
- Sintaxis reciente que un motor sabía leer y el otro todavía no.
- Helpers de transpilación inyectados con una forma en dev y otra en build.
- Optimizaciones que Rollup aplicaba al empaquetar y que esbuild no replicaba al servir.
La asimetría llegaba incluso al rendimiento del propio build. El dev era instantáneo gracias a esbuild, pero el vite build heredaba la velocidad de Rollup en JavaScript, notablemente más lento en proyectos grandes. Tenías lo mejor de cada mundo en su fase, y también lo peor de la frontera: un dev rapidísimo, un build comparativamente pesado, y una tierra de nadie entre ambos donde vivían las divergencias.
Rolldown unifica
Rolldown es la respuesta a esa tensión. Es un bundler escrito en Rust, deliberadamente compatible con la API de plugins de Rollup, y construido sobre Oxc —el Oxidation Compiler—, que aporta un parser, un resolver y un transformador que comparten un único AST. La jugada es elegante: conservar la interfaz que el ecosistema ya conoce, y sustituir el motor por debajo por uno más rápido y unificado.
En Vite 8, Rolldown pasa a ser el bundler único: reemplaza a esbuild en el pre-empaquetado de dependencias y a Rollup en el build de producción. Por primera vez, dev y build recorren el mismo motor, con el mismo parser y la misma semántica. La costura material desaparece, y con ella buena parte de las divergencias que nacían de tener dos AST distintos leyendo el mismo archivo.
# La transicion se probo primero con un paquete puente
npm install rolldown-vite # Vite con Rolldown como motor unico
# En Vite 8 es el camino por defecto: un solo bundler en dev y en build
El puente rolldown-vite no fue un experimento improvisado: se probó en proyectos reales antes de que Vite 8 lo adoptara por defecto, precisamente para verificar que la compatibilidad con la API de Rollup aguantaba el peso del ecosistema. Que la inmensa mayoría de los plugins funcionara sin cambios fue la señal de que la interfaz estaba bien elegida y el motor podía sustituirse sin romper a nadie.
La clave técnica que lo hace posible es Oxc. Al compartir un solo AST entre el parser, el resolver, el transformador y el bundler, Rolldown parsea tu código una vez y reutiliza esa representación en cada fase, en lugar de reparsearlo con reglas ligeramente distintas en cada herramienta. De ahí sale a la vez la velocidad —parsear una vez es más barato que parsear cuatro— y la coherencia —una sola semántica, no dos que casi coinciden—.
Oxc no es solo un parser: es una familia de herramientas sobre un mismo árbol.
- Un parser y un resolver en Rust que siguen el algoritmo de Node y el campo
exports. - Un transformador que sustituye a Babel para bajar TypeScript y JSX a sintaxis del target.
oxlintyoxfmt, linter y formateador que reutilizan ese AST en vez de reparsear.- Rolldown como bundler, que cierra el círculo con una sola representación de punta a punta.
// Tu vite.config.ts no cambia: la interfaz de Rollup se conserva
export default defineConfig({
plugins: [/* plugins de Rollup existentes siguen funcionando */],
build: { target: "es2022" },
});
Unificar el motor abre además una posibilidad que antes era cara: un modo de bundle completo también en desarrollo. Como el mismo Rolldown puede empaquetar rápido, dev puede acercarse al comportamiento de producción cuando te interesa fidelidad en lugar de máxima granularidad, sin cambiar de herramienta. La Environment API, que verás en el siguiente nivel, se apoya en esta unificación para orquestar varios entornos con un único motor debajo.
Lo que Vite 8 gana al unificar el motor se resume en tres frentes:
- Coherencia: dev y build parsean con las mismas reglas, y la clase de bugs por divergencia de motor se extingue.
- Velocidad: el build hereda el rendimiento de Rust y acaba con el
vite buildlento sobre Rollup. - Simplicidad: una sola pieza que mantener y razonar, en vez de coordinar dos motores en su frontera.
esbuild
La primera revolución de velocidad: un bundler en Go, cien veces más rápido, que hizo viable no empaquetar en dev. Limitado en salida y plugins.
Rollup
El estándar de calidad: el mejor tree shaking y la API de plugins que todos adoptaron. Maduro, pero atado a la velocidad de JavaScript.
Rolldown
La síntesis: la interfaz de Rollup reimplementada en Rust sobre Oxc. Un único motor para dev y build, rápido y coherente a la vez.
flowchart TD subgraph Antes A1[Dev con esbuild en Go] A2[Build con Rollup en JS] end subgraph Ahora B1[Rolldown en dev y en build] end A1 --> G[Dos parsers y dos semanticas] A2 --> G B1 --> U[Un parser y una semantica sobre Oxc] style A1 fill:#f9e2af,color:#11111b style A2 fill:#cba6f7,color:#11111b style B1 fill:#a6e3a1,color:#11111b style U fill:#a6e3a1,color:#11111b
La historia de Vite es un caso de manual del principio que gobierna todo el toolchain moderno: se estabilizan interfaces y se reemplazan motores. La interfaz relevante aquí es la API de plugins de Rollup, tan buena que se volvió el lenguaje común del empaquetado. Vite nunca la abandonó; lo que hizo fue jugar con los motores debajo de ella. Al principio necesitó dos —esbuild por velocidad en dev, Rollup por calidad en build—, y pagó por ello el precio de una costura: dos AST, dos semánticas, una frontera donde anidaban los bugs. Rolldown es la síntesis: reimplementa la interfaz de Rollup en Rust, sobre el AST compartido de Oxc, de modo que el ecosistema de plugins sigue funcionando mientras el motor se unifica y acelera. Fíjate en lo que no cambia para ti: tu vite.config.ts, tus plugins, tu forma de pensar el build. Y fíjate en lo que sí mejora: dev y build dejan de correr sobre motores distintos, así que la clase de divergencias que nacía de esa diferencia material se extingue en su origen. Esta es la moraleja estratégica que debes llevarte: no apuestes por el motor de moda —esbuild, Rollup, Rolldown, el que venga—, apuesta por la interfaz que persiste. Quien aprendió la API de Rollup en 2020 sigue vigente en 2026 con Rolldown sin reaprender nada, porque aprendió el cimiento y no el andamio. Y quien entiende que unificar el motor era la última pieza para cerrar la brecha dev/build comprende por qué esta transición no es una moda de rendimiento, sino la culminación arquitectónica de las dos naturalezas bajo un solo corazón.
- Abre la documentación histórica de Vite y localiza la frase que advertía de diferencias entre el esbuild de dev y el Rollup de build.
- Instala
rolldown-viteen un proyecto pequeño o crea uno con Vite 8 y confirma en su salida qué motor empaqueta en cada fase. - Comprueba que un plugin de Rollup que usabas sigue funcionando sin cambios: es la prueba de que la interfaz se conservó.
- Cronometra
vite buildcon el motor en Rust y compáralo con un build antiguo sobre Rollup en un proyecto grande. - Explica en dos frases por qué compartir un solo AST vía Oxc reduce las divergencias dev/build en su raíz.