Qwik: El Framework con la carga de JavaScript más eficiente

0
1714
Logo del framework qwik

0. Índice de contenidos

  1. ¿Que es Qwik?
  2. Problemas que tenemos en la actualidad
  3. ¿Posible solución al problema?
  4. Solución propuesta por Qwik
  5. ¿Por qué es importante la velocidad de las páginas?
  6. Qué hacen los competidores y que hace Qwik
  7. Prueba práctica
  8. Conclusiones
  9. Referencias

1. ¿Que es Qwik?

Se trata de un nuevo framework cuya versión 1.0.0 ha salido el 2 de mayo de 2023. El punto fuerte de este framework es la carga casi instantánea de nuestras aplicaciones web, independientemente del tamaño de las mismas o la complejidad de estas.

Esto lo consigue gracias a dos estrategias principales:

  • Retrasa todo lo que puede la descarga y ejecución de los archivos JavaScript de nuestra aplicación web.
  • Serializa el estado de ejecución de la aplicación y framework en el servidor y reanudarlo en el cliente.

El objetivo de este framework es el de optimizar al máximo la carga inicial de datos de nuestras aplicaciones web, solo descargando y ejecutando lo mínimo necesario.

Para conseguir esta carga instantánea Qwik ha seguido un planteamiento diferente al que tienen otros frameworks actuales, siguiendo dos estrategias, que serían mediante la serialización y reanudabilidad.

2. Problemas que tenemos en la actualidad

¿Cuál sería uno de los principales problemas que existen actualmente el desarrollo de aplicaciones web? Hoy en día, las páginas web necesitan una gran cantidad de JavaScript para ser interactivas. Y que haya tanto JavaScript se manifiesta en dos problemas:

  1. Ancho de banda: Se envía una gran cantidad de código al cliente, esto hace que para las redes con un ancho de banda más lento requieran de mucho más tiempo para la descarga del mismo.
  2. Tiempo de puesta a punto (Startup time): Una vez en el cliente, el código necesita ser ejecutado para poder hacer el sitio web interactivo.

A medida que nuestras aplicaciones web vayan evolucionando y se vuelvan más complejas, la cantidad de código JavaScript que tienen irá aumentando. A medida que aumente la cantidad de líneas JavaScript el desempeño de la carga inicial de la aplicación sera peor.

3. ¿Posible solución al problema?

La solución a los problemas comentados anteriormente parece ser clara, pero no sencilla de aplicar, y sería la de cargar menos código JavaScript al inicio. Al reducir la cantidad de código JavaScript el rendimiento de nuestras páginas web debería ser mejor.

Pero no es un problema que sea sencillo de resolver, la mayoría de herramientas con las que contamos hoy en día funcionan de una manera que hace que la carga de JavaScript aumente. Esto es así porque estas herramientas están diseñadas para solventar un problema en específico sin tener en cuenta la cantidad de código que se va a generar.

La industria ha fallado en tener en cuenta la implicación del tamaño del bundle. Como desarrolladores, muchas veces introducimos librerías sin tener en cuenta lo que implica en el tamaño del bundle. El tamaño de este es un problema que aparece cuando juntas todas las piezas de tu aplicación y ves que acaba siendo muy grande, en ese punto, como desarrollador se tienen pocas opciones para optimizarlo como se debería.

Media de tamaño de bundle en diferentes frameworks (2020)
Media de tamaño de bundle en diferentes frameworks (en KB) (2020)

4. Solución propuesta por Qwik

Desde el inicio Qwik ha sido diseñado con el problema del tamaño del bundle en el foco. El objetivo inicial de este framework es el de contar con un tamaño de bundle pequeño, y todas las decisiones que se tomen a partir de ahí van a ser dadas en base a este objetivo.

Lo que pretende es no tener que cargar todo el código en la puesta a punto de nuestra aplicación. Por lo tanto, el objetivo no es crear menos JavaScript, sino posponer lo máximo posible la carga del mismo.

Para conseguir esto hay que plantear de una manera diferente el diseño de nuestra aplicación, pero gracias a esto lo que vamos a obtener es una descarga casi ínfima de JavaScript en la carga inicial de nuestra aplicación, y que la descarga del mismo sea progresiva.

¿Qué significa este término? De lo que trata es de que se vaya descargando el código en base a las necesidades de la aplicación, no teniendo que descargar todo antes de tiempo. Por ejemplo, no descargar el event handler de un botón hasta hacer click en el mismo. Este concepto nos conecta al objetivo principal de Qwik, que es el de retrasar la descarga de JavaScript lo máximo posible.

5. ¿Por qué es importante la velocidad de las páginas?

La pregunta es ¿Es tan importante la velocidad de carga de una página web como para que tengamos que tener tan en cuenta el tamaño del bundle? La respuesta es que sí, forma una parte muy importante del éxito que puede tener tu página, ya que puede impactar en la clasificación de motores de búsqueda, al grado de satisfacción del cliente o al ratio de conversión.

Por aquí dejo una serie de casos de mejoras en algunas compañías al optimizar la velocidad de carga sacados de web.dev

  • Por cada 100 ms más de rapidez → 1% más de conversiones
    Para Mobify, cada disminución de 100 ms en la velocidad de carga de la página de inicio resultó en un aumento del 1.11% en la conversión basada en sesiones, lo que generó un aumento promedio de ingresos anuales de casi $380,000.
  • 50% más rápido → 12% más de ventas
    Cuando AutoAnything redujo a la mitad el tiempo de carga de la página, observaron un aumento del 12% al 13% en las ventas.
  • 20% más rápido → 10% más de conversiones
    El minorista Furniture Village auditó la velocidad de su sitio y desarrolló un plan para abordar los problemas que encontraron, lo que resultó en una reducción del 20% en el tiempo de carga de la página y un aumento del 10% en la tasa de conversión.
  • 40% más rápido → 15% más de registros
    Pinterest redujo los tiempos de espera percibidos en un 40% y esto aumentó el tráfico de motores de búsqueda y los registros en un 15%.
  • 850 ms más rápido → 7% más de conversiones
    COOK redujo el tiempo promedio de carga de la página en 850 milisegundos, lo que aumentó las conversiones en un 7%, disminuyó las tasas de rebote en un 7% y aumentó las páginas por sesión en un 10%.
  • 1 segundo de lentitud → 10% menos de usuarios
    La BBC descubrió que perdieron un 10% adicional de usuarios por cada segundo adicional que su sitio tardaba en cargar.

6. Qué hacen los competidores y que hace Qwik

Resumable vs. Hydration

Para entender bien que es lo que hace diferente a Qwik, hay que entender cómo trabajan el resto de framework actualmente.

Cuando se inicia una aplicación de tipo Static Site Generation (SSG)/Server Side Rendering (SSR) en el cliente, requiere que el framework en el cliente restaure tres piezas de información:

  1. Listeners: Tiene que localizar todos los event listener que hay en la aplicación para posteriormente instalarlos en los nodos del DOM y así hacer que la aplicación sea interactiva.
  2. Árbol de componentes: Tienen que construir una estructura de datos interna que represente el árbol de componentes.
  3. Estado de la aplicación: Tiene que restaurar el estado de la aplicación.

A esto se le llama hydration, y es el proceso que realizan los todos los frameworks actuales para hacer una aplicación interactiva.

La hydration no es el proceso más práctico, ya que los frameworks que siguen esta metodología tienen que descargar todo el código relacionado con los componentes de la página que se vaya a cargar. Otro problema, es que también tienen que ejecutar las plantillas asociadas con los componentes de la página para reconstruir todo el posicionamiento de los listeners y el árbol de componentes interno.

Comparativa entre Resumable e Hydration
Comparativa entre Resumable e Hydration

Qwik es diferente por que no requiere de este proceso para reanudar una aplicación en el cliente. Al no contar con este proceso, conseguimos que la carga inicial sea casi instantánea.

Resumability

De lo que trata la resumability es de pausar la ejecución en el servidor y restaurarla en el cliente sin tener que repetir y descargar toda la lógica de la aplicación. Es decir, que en cualquier momento de la ejecución de nuestra aplicación podamos serializar el estado y reanudarlo en el momento que fue serializado.

Para conseguir esto, tenemos que resolver los tres problemas relacionados a lo que comentamos antes con la hydration (Listeners, árbol de componentes y estado de la aplicación)

Listeners

Lo que se hace actualmente en los diferentes framework que existen para resolver la escucha de eventos es que primero van a descargar los componentes y posteriormente van ejecutar sus plantillas para poder obtener los event listener que se encuentran en el DOM. Esta forma de hacerlo tiene una serie de problemas:

  • Requiere que el código de la plantilla sea descargado y ejecutado de manera anticipada.
  • Requiere que el código encargado de manejar el evento ( event handler) sea descargado de manera anticipada, para poder juntarlo con el componente en el DOM.

Esta manera de hacerlo no es escalable. A medida que nuestra aplicación vaya creciendo, ganando más funcionalidades y siendo más compleja, tendrá que descargar y ejecutar más código muy pronto. Esto afectará al tiempo de carga inicial de la aplicación, y por ende a la experiencia de usuario.

¿Que hace Qwik para resolver este problema?

Serializa los event listener en el DOM

Imagen con ejemplo de como serializa los event listener en el DOM

Al igual que los otros framework, Qwik necesita obtener la información de los event listener, pero esto lo hace en el proceso de SSG/SSR. Lo que se genera tras el SSG/SSR ya se encuentra serializado en el HTML, por lo que el buscador no debe realizar ninguna acción para reanudar con la ejecución. El atributo onclick de la imagen cuenta con toda la información necesaria para reanudar la aplicación sin la necesidad de hacer nada de manera anticipada.

  1. Qwikloader setea un listener global en lugar de varios listener para cada uno de los elementos del DOM sin la necesidad de contar con el código de la aplicación.
  2. El HTML contiene una url al chunk y al nombre del simbolo. Con esta información Qwikloader sabe que code chunk tiene que descargar y que símbolo tiene que traer del chunk.
  3. Para hacer todo lo anterior posible, la implementación del procesado de eventos de Qwik entiende la asincronía y permite la inserción del lazy loading.

Árbol de componentes

Los frameworks trabajan con el árbol de componentes, y para esto, necesitan tener un conocimiento completo del mismo para saber qué componentes tienen que renderizar y cuando. Lo que ocurre actualmente con los datos de salida de una app SSR/SSG es que la información de los límites del componente es destruida. Es decir, que no habrá manera de saber cuales son los límites únicamente mirando el código HTML generado. Por lo que para recrear esta información, los frameworks vuelven a ejecutar la plantilla del componente para cachear (memoizar) la localización de los límites del componente. Que es de lo que trata la hydration. Cosa que la hace costosa, ya que hay que requiere de la descarga y ejecución de la plantilla del componente.

Lo que hace Qwik es obtener la información de los límites de los componentes en el proceso de SSR/SSG y la serializa en el HTML. Haciendo esto se consigue lo siguiente:

  • Reconstruir la información de jerarquía de componentes sin la necesidad de tener datos del código del componente mismo. Él mismo puede permanecer en un estado lazy.
  • Puede hacer esto de manera lazy solo para los componentes que necesitan ser renderizados de nuevo en lugar de hacer todo por adelantado.
  • Recolecta información entre los store y los componentes. Esto crea un modelo de suscripción que permite conocer a Qwik que componentes necesitan ser renderizados de nuevo en caso de que se actualice algún estado. Esta información de la suscripción queda serializada en el HTML.

Estado de la aplicación

Los frameworks actuales suelen tener una manera de serializar los datos del estado de la aplicación en el HTML, para así poder restaurarlo en el proceso de hydration. En este aspecto son bastante similares Qwik. A pesar de eso, la gestión de estado de Qwik está más estrechamente relacionada con el ciclo de vida de los componentes. Esto significa que se puede retrasar la carga del componente independientemente del estado del mismo. Esto es algo que no es fácil de conseguir en la mayoría de frameworks, ya que las propiedades del componente suelen venir dadas por el componente padre, creando así una reacción en cadena para la restauración de un componente. Qwik permite a cualquier componente ser reanudado sin la necesidad de tener presente el código del componente padre.

Flujo que sigue Qwik

Proceso que sigue Qwik para montar la página web

7. Prueba práctica

La mejor manera de ver alguna de las cosas que ofrece es realizando una prueba práctica creando una aplicación básica y comprobar cómo es trabajar con este framework y las diferencias que se pueden apreciar.

Para empezar, primero tendremos que crear un proyecto que se puede realizar con uno de los siguientes comandos

npm create qwik@latest
pnpm create qwik@latest
yarn create qwik

Se nos darán una serie de opciones para crear un nuevo proyecto, yo seleccionare la de crear un proyecto vacío, ya que queremos empezar desde cero.

Imagen con opciones de creación de proyecto de Qwik con la casilla de empty app seleccionada

Una vez creado el proyecto, Qwik nos propone la siguiente estructura de carpetas.

Imagen de estructura de carpetas propuesta por Qwik

Nos encontraríamos con la carpeta de components, en la que la configuración de Qwik se nos comenta que podemos cambiar a voluntad si nos parece.

La otra carpeta con la que nos vamos a encontrar es la de routes, que se trata de un directorio especial que utiliza Qwik City (meta-framework) para tratar con las diferentes páginas y poder navegar entre ellas, el routing se basa en un la estructura de ficheros (al igual que Next.js, Svelte..etc). Todos los archivos y directorios dentro de esta carpeta tienen un rol en el routing de la aplicación.

Se ha creado una aplicación TODO básica con la única funcionalidad de ir añadiendo tareas y posteriormente mostrarlas. Lo primero que me ha llamada la atención a la hora de trabajar con Qwik es el uso del optimizador que tiene, por ejemplo, he creado el siguiente formulario para añadir las tareas.

Imagen de formulario hecho con qwik

Este componente form viene dado por Qwik City, y, si nos fijamos en como gestiona el submit por dentro esta librería veremos que cuenta con un símbolo de dólar.

Imagen de submit dado por la librería

Este símbolo de dólar lo que indica es que se va a utilizar el optimizador de Qwik, esto permitirá que Qwik haga el lazy loading de datos cuando sea necesario, en este caso al hacer la acción de submit, esto lo veremos de manera visual más adelante.

Para entender de manera visual como funciona Qwik, vamos a ver lo que se muestra en el HTML.

Imagen del formulario de qwik en html

Si nos fijamos, en la parte del formulario se ha creado una referencia al código serializado de nuestro event handler de submit, para que una vez interactuemos con el formulario en este caso, descargue el código necesario para poder manejar el evento.

En esta imagen mostraremos los archivos que se descargan al cargar la página por primera vez cuando estamos en desarrollo, los archivos JavaScript que vemos, son propios del entorno de desarrollo, en producción no estarían.

Imagen de la vista de network antes de añadir la tarea

En la siguiente imagen mostraremos lo que se descarga al añadir una tarea con el formulario.

Imagen de los archivos Javascript descargados al interactuar con el botón de submit

Vemos que se ha descargado una serie de código JavaScript para poder manejar este evento, si miramos uno de los archivos que ha descargado, podemos encontrar al encargado de manejar el evento de submit en el formulario.

Encargado de realizar el evento de submit

Una vez haya descargado este código JavaScript, no será necesario descargarlo de nuevo en caso de que se vuelva a requerir.

Comparativa con NextJS

Para comparar la cantidad de código JavaScript que es descargado al inicio, he creado el mismo tipo de aplicación con NextJS, y las compararemos en modo de producción.

A continuación se va a mostrar los archivos que se cargan inicialmente al cargar la página por primera vez en NextJS.

Imagen de la pestaña de network donde se muestran los archivos descargados al renderizar la página por primera vez en Next

Vemos que se han descargado casi unos 80kB de JavaScript en esta aplicación.

Ahora veremos los resultados de esta misma aplicación creada con Qwik

Imagen de la pestaña de network donde se muestran los archivos descargados al renderizar la página por primera vez en Qwik

Aquí vemos apreciar que la cantidad de JavaScript que descarga es nula.

8. Conclusiones

Qwik es un nuevo framework que pone puntos muy interesantes sobre la mesa, con el cometido principal de optimizar carga de JavaScript en la aplicación lo máximo posible mediante diferentes estrategias de carga, reduciendo todo lo posible el tamaño del bundle inicial, ahorrando muchos quebraderos de cabeza a la hora de diseñar un proyecto con diferentes estrategias de carga de datos, ya que todo esto viene por defecto con el framework.

Una ventaja adicional que proporciona es la capacidad de utilizar React dentro de Qwik. Esto significa que podemos aprovechar las librerías y componentes existentes de React dentro de Qwik, lo que facilita la transición a este nuevo framework. No sería tan complicado migrar a Qwik porque podemos reutilizar gran parte del código y las habilidades que ya tenemos en React.

Con esto no quiero decir que Qwik sea la panacea al desarrollo de Software en Front y que vaya a ser la opción a elegir siempre por todas estas ventajas que ofrece. La elección del framework dependerá del tipo de proyecto que vayamos a querer desarrollar, pero en el caso de que el tipo de proyecto sea uno en el que queremos centrarnos en la eficiencia del mismo y una buena gestión de recursos, Qwik es un candidato que cumple a la perfección con estos objetivos.

9. Referencias

Documentación de Qwik
Artículo de Medium haciendo comparativa entre Frameworks

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad