Qwik: la apuesta por la resumibilidad en lugar de hidratación
Índice de contenidos
- Puntos clave
- Resumibilidad frente a hidratación
- Qué dicen los números
- Qwik City y el ecosistema
- Dónde compensa y dónde no
- Adopción real
- Conclusión
- Preguntas frecuentes
- ¿Qué diferencia hay entre resumibilidad e hidratación?
- ¿Cuánto mejora Qwik el TTI y el LCP frente a Next.js?
- ¿Puedo reutilizar mis componentes React en Qwik?
- Fuentes
Qwik apuesta por la resumibilidad en vez de la hidratación: el servidor serializa el estado en el propio HTML y el cliente no descarga nada hasta que el usuario interactúa, así que el bundle inicial de aplicación es cero kilobytes. En Lighthouse eso se traduce en un TTI por debajo de 0,5 segundos, aunque no compensa para equipos ya invertidos en React ni para apps con estado colaborativo en tiempo real.
Hidratar una aplicación React o Vue consiste en volver a ejecutar en el navegador el mismo código que ya corrió en el servidor. Solo sirve para recuperar los manejadores de eventos y el árbol de estado que se perdieron al serializar el HTML. Es un peaje silencioso que pagamos en cada carga: el bundle se descarga, se parsea y se ejecuta antes de que el botón responda.
Qwik, el framework que Misko Hevery (creador de Angular) impulsa desde Builder.io, ataca el problema con la resumibilidad. En lugar de rehidratar, el cliente reanuda la ejecución donde el servidor la dejó, y solo descarga el código cuando hace falta.
Puntos clave
-
El bundle inicial de aplicación es cero kilobytes: el HTML llega completo y el runtime de Qwik (~4 KB) escucha globalmente.
-
El
$marker no es azúcar sintáctico: es la frontera de lazy loading que el compilador Vite respeta para generar chunks independientes por cada evento. -
En Lighthouse, landing pages con Qwik logran TTI por debajo de 0,5 s y LCP alrededor de 0,6 s de forma consistente.
-
La ventaja crece con el tamaño: en una tienda de 50 componentes, Next.js hidrata el árbol visible completo; Qwik solo descarga el handler del botón pulsado.
-
No es para todos: teams con inversión en React, apps colaborativas realtime o sitios casi estáticos tienen mejores alternativas.
Resumibilidad frente a hidratación
En el modelo clásico el servidor renderiza HTML y el navegador lo pinta. Después descarga el bundle de JavaScript (entre 100 y 300 KB en aplicaciones medianas) para reconstruir el estado y enganchar los listeners. Hasta que ese proceso termina, la página parece viva pero no responde. Lighthouse lo mide como la brecha entre First Contentful Paint y Time to Interactive, el hueco que describe la documentación oficial de Qwik sobre resumibilidad[1].
Qwik hace otra cosa. El servidor serializa en el propio HTML todo lo necesario (estado, referencias a los manejadores, cierre de closures) dentro de atributos y un bloque JSON al final del documento. El cliente descarga HTML y nada más. Un runtime de unos pocos kilobytes escucha los eventos globalmente mediante delegación; cuando el usuario pulsa un botón, Qwik sabe qué chunk hay que pedir y lo descarga en ese instante.
La página está interactiva desde el primer byte, aunque el código detrás de cada acción llegue bajo demanda. Builder.io, la empresa detrás del framework, lo compara directamente con la hidratación clásica[2]: la resumibilidad recupera el estado como resultado de la interacción, la hidratación tiene que ejecutarse antes de ella.
La pieza que hace esto posible es el marcador $. Cuando escribimos onClick$ o envolvemos un componente en component$, el compilador Qwik (basado en Vite) corta ahí el grafo de dependencias y genera un chunk independiente. Ese símbolo no es azúcar sintáctico: es la frontera de lazy loading que el optimizador respeta. Por eso los componentes se ven parecidos a React, pero el bundle resultante no se parece en nada.
import { component$, useSignal } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
export const useUser = routeLoader$(async ({ params }) => {
return await db.user.findById(params.id);
});
export default component$(() => {
const user = useUser();
const count = useSignal(0);
return (
<section>
<h1>{user.value.name}</h1>
<button onClick$={() => count.value++}>
Visitas: {count.value}
</button>
</section>
);
});
Qué dicen los números
En landing pages y blogs con algo de interactividad, los benchmarks publicados durante 2024 son consistentes:
-
Lighthouse: puntuación de 100.
-
TTI: por debajo de 0,5 s.
-
LCP: alrededor de 0,6 s.
-
Bundle inicial: cero kilobytes de JavaScript de aplicación.
Un Next.js equivalente suele moverse entre 80 y 150 KB de JS inicial y un TTI de 1 a 2 s en conexiones 4G. La diferencia no es marginal y se acentúa en móvil con red lenta, justo donde Core Web Vitals[3] exige un LCP bajo 2,5 s para contar como «bueno».
El matiz importante: esos números son sostenibles cuando la aplicación crece, porque el coste de interactividad es proporcional a lo que el usuario toca, no al tamaño total del código. Comparar con SvelteKit 1.0 y su adopción real da perspectiva: SvelteKit también tiene bundles pequeños, pero no resuelve el problema de la hidratación de la misma forma.
Qwik City y el ecosistema
Qwik City es al framework lo que SvelteKit es a Svelte: routing por ficheros, routeLoader$ para datos en el servidor, routeAction$ para formularios y SSR por defecto. Los adaptadores estables cubren Vercel, Cloudflare Pages, Netlify, Node y despliegue estático. Con Qwik 1.5[4], lanzado el 4 de marzo de 2024, los adaptadores dejaron de tener sorpresas en producción y la integración con Vite 5 es sólida.
El ecosistema sigue siendo pequeño comparado con React:
-
Componentes: Qwik UI y Modus.
-
Formularios:
modular-forms. -
Estado global: los signals integrados suelen bastar.
-
Testing: Vitest y Playwright.
-
Interoperabilidad React:
qwik-reactpermite islands, pero con coste de perder la resumibilidad en esos nodos.
Dónde compensa y dónde no
Qwik brilla cuando la métrica crítica es el TTI en móvil y la página tiene interactividad real sin ser una SPA de estado masivo. Ahí entran e-commerce, portales de contenido con comentarios, marketing sites con configuradores y dashboards públicos. En esos escenarios el bundle cero se traduce directamente en conversión: cada 100 ms de mejora en LCP mueve la aguja en tiendas medianas.
Qwik no compensa en casos igual de claros. Un equipo con años de inversión en React paga un coste alto por migrar. Para apps cliente-pesadas (editores colaborativos, herramientas realtime) el código acaba cargándose igual, y Qwik no aporta tanto frente a una buena partición de rutas en Next.js. Para sitios casi estáticos con islands puntuales, Astro sigue siendo una elección más simple con acceso directo al ecosistema React.
Adopción real
La adopción está en fase early. Builder.io usa Qwik para su propio marketing, Daily.dev lo incorpora parcialmente y hay casos reportados en shops medianos como alternativa a Shopify Hydrogen. Algunas agencias europeas lo venden como ventaja competitiva en Core Web Vitals. No es un stack mayoritario, pero el concepto de resumibilidad ya influye en otros frameworks: React Server Components persiguen un objetivo parecido por otro camino.
Conclusión
Qwik resuelve bien un problema real y lo hace con una idea que merece existir. Para un greenfield donde el rendimiento es un KPI y el equipo puede permitirse un paradigma nuevo, la elección es defendible. En el escenario de interactividad bajo demanda es técnicamente superior a casi cualquier alternativa.
Para el resto, que es la mayoría, SvelteKit, Astro o Next.js con App Router siguen siendo apuestas más seguras. Sigo pensando que Qwik no necesita ganar la guerra de los frameworks para haber dejado huella: ya ha demostrado que la hidratación no es inevitable, y eso cambia la vara de medir del resto.
Lee también la versión en inglés: Qwik: Betting on Resumability Instead of Hydration.
Fuentes:
- Resumable (documentación oficial de Qwik)[1]
- Resumability vs Hydration (blog de Builder.io)[2]
- Web Vitals (web.dev)[3]
- Release v1.5.0 (GitHub, QwikDev/qwik)[4]
Preguntas frecuentes
¿Qué diferencia hay entre resumibilidad e hidratación?
Hidratar consiste en volver a ejecutar en el navegador el código que ya corrió en el servidor, para recuperar manejadores de eventos y estado. Eso exige descargar y ejecutar un bundle de 100 a 300 KB antes de que la página responda. Con la resumibilidad de Qwik el servidor serializa estado y manejadores dentro del propio HTML. El cliente descarga solo HTML más un runtime de unos 4 KB que escucha eventos por delegación; el chunk de cada acción se pide cuando el usuario la ejecuta.
¿Cuánto mejora Qwik el TTI y el LCP frente a Next.js?
En landing pages y blogs con algo de interactividad, los benchmarks publicados durante 2024 dan puntuación Lighthouse de 100. El TTI queda por debajo de 0,5 s, el LCP alrededor de 0,6 s y el JavaScript de aplicación inicial en cero kilobytes. Un Next.js equivalente suele moverse entre 80 y 150 KB de JS inicial y un TTI de 1 a 2 s en 4G. La ventaja se acentúa en móvil con red lenta y crece con el tamaño de la aplicación, porque el coste es proporcional a lo que el usuario toca.
¿Puedo reutilizar mis componentes React en Qwik?
Sí, mediante qwik-react, que permite incrustarlos como islands, pero a costa de perder la resumibilidad en esos nodos. Un equipo con años de inversión en React paga un coste alto por migrar. Hay dos casos donde Qwik no compensa: las apps cliente-pesadas como editores colaborativos o herramientas realtime, donde el código acaba cargándose igual. Y los sitios casi estáticos con islands puntuales, donde Astro es más simple y da acceso directo al ecosistema React.