Construyendo una Aplicación Web: El Camino Fácil y el Camino de Alto Rendimiento. ¿Por qué no son lo mismo?

Rate this content
Bookmark

Utilizamos frameworks para facilitar la construcción de nuestras aplicaciones. Sin embargo, a medida que la aplicación crece, su rendimiento se ve afectado. No hay una sola cosa, sino una muerte por mil cortes. Los desarrolladores están bajo presión y a menudo eligen el camino fácil y rápido para entregar una funcionalidad en lugar del camino de alto rendimiento. El camino de alto rendimiento suele requerir más trabajo. Así que veamos estos dos caminos e imaginemos un mundo donde el camino de alto rendimiento sea el camino rápido y fácil.

Miško Hevery
Miško Hevery
31 min
01 Jun, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Misko Havry se presenta y analiza el impacto de JavaScript en el rendimiento. Se exploran los conceptos de reconciliación, hidratación y resumibilidad, junto con la importancia de un código limpio y la optimización del compilador. La charla incluye demostraciones de componentes de la aplicación y muestra el poder de la extracción de código. Se destaca el framework QUIC por su capacidad para optimizar la carga de código y priorizar las interacciones. Se utiliza el service worker para descargar selectivamente componentes y mejorar el rendimiento. También se discuten el SEO y la depuración en QUIC, junto con comparaciones con otros frameworks.

Available in English

1. Introducción a Misko Havry y Rendimiento

Short description:

Comencemos con una broma sobre cómo se separan las funciones. Soy Misko Havry, el creador de AngularJS y Quik. También tenemos Partytown y mitosis. Hablemos sobre el rendimiento y cómo JavaScript puede afectarlo.

Entonces, con eso, comencemos. Feliz Android. Gracias, chicos. Gracias. Creo que también debemos aplaudir a nuestros presentadores. No podría hacer su trabajo. Así que voy a empezar con una broma, porque me encantan las bromas malas cuando soy papá. ¿Cómo se separan las funciones? Dejan de llamarse entre sí. Y en realidad es una broma relevante. Porque vamos a mostrarles cómo se separan las funciones en esta presentación.

Así que hola, soy Misko Havry. Es posible que me conozcan, porque he creado esta cosa llamada AngularJS, y ahora estoy trabajando en esta cosa llamada Quik, y espero que hayan oído hablar de builder.io. Es un sistema de CMS visual sin cabeza. Lo que es, es Imagina Wix, pero sin alojamiento. En su lugar, npm instálalo dentro de tu aplicación. Arrástralo y luego obtendrás edición visual. Y también puedes, porque es tu aplicación, registrar tus propios componentes con él y dejar que tus especialistas en marketing se vuelvan locos. Y no tienen que molestarte a ti, el ingeniero, para cambiar cualquier cosa en sus páginas de destino.

Ahora, también hacemos otras cosas. Hacemos Quik. Pero también tenemos esta cosa llamada Partytown, que mueve el código de terceros a web workers. Y hacemos mitosis, que te permite escribir tu código una vez. Y generamos código canónico para React, Angular, Vue, Svelte y cualquier otra cosa que puedas imaginar. Pero hablemos sobre el rendimiento. Esto es más o menos un conjunto típico seleccionado al azar de sitios web de la web. Y observa, todos son más o menos verdes, tal vez algunos amarillos. Realmente no se ve tan bien. ¿Por qué es eso? Sabes, si construyes una aplicación de hola mundo simple y la publicas en algún lugar, el rendimiento es genial, pero una vez que le pones aplicaciones reales, ya sabes, tráfico real detrás de ella, el rendimiento no va tan bien. Y hay muchas razones diferentes para ello, pero una cosa de la que realmente voy a tratar de convencerte es que es JavaScript. Y básicamente, demasiado de él.

2. JavaScript y Hidratación

Short description:

Este es un gráfico del archivo HTTP que muestra la cantidad creciente de JavaScript que se envía a los navegadores con el tiempo. Los usuarios esperan aplicaciones complejas que requieren JavaScript. Cuanto más JavaScript se envíe, menor será la puntuación de Light House. La hidratación es una solución alternativa que crea un problema. Anteriormente, las aplicaciones se iniciaban enviando HTML vacío y cargando JavaScript. Para eliminar la pantalla en blanco, se introdujo el prerenderizado en el lado del servidor, pero carece de interactividad hasta que se descargue y ejecute el JavaScript.

Y si lo observas, este es un gráfico del archivo HTTP. Esta es la cantidad de JavaScript que hemos estado enviando a nuestros navegadores con el tiempo. Y como puedes ver, eso solo está aumentando, aumentando, aumentando. Y apostaría a que en el futuro, habrá aún más JavaScript. Y tiene total sentido porque la experiencia de nuestros usuarios espera aplicaciones ricas y complicadas. Y no se pueden entregar aplicaciones complejas sin JavaScript. Así que necesitamos JavaScript.

Sabes, ¿existe un mundo en el que dejemos de enviar JavaScript o no? Este es otro gráfico interesante del archivo HTTP. He seleccionado algunos frameworks aquí. Esto no es importante. Lo que quiero mostrarte aquí es que la puntuación mediana que obtiene el sitio web y la cantidad de JavaScript que se envía son inversamente proporcionales, ¿verdad? Cuanto más JavaScript envíes, menor será tu puntuación de Light House. Y cuanto menos JavaScript envíes, mejor será tu puntuación de Light House. Eso no debería ser sorprendente. Debería ser evidente, ¿verdad? Que cuanto menos JavaScript envíes, mejor será la cosa. El problema es que la forma en que funcionan nuestras aplicaciones es que tenemos esta cosa llamada hidratación.

Y la hidratación es esta solución alternativa interesante que hemos creado y que está creando este problema. Permíteme explicarlo. Antes, cuando no teníamos meta frameworks como Next.js, la forma en que las aplicaciones se iniciaban era enviando HTML. El HTML estaría vacío. Y en el HTML habría una etiqueta de script que cargaría JavaScript. JavaScript ejecutaría tu aplicación, la aplicación causaría un renderizado y luego el renderizado crearía un sitio web y ahora puedes interactuar con el sitio web. Pero dijimos, ¿sabes qué? Realmente no nos gusta el hecho de que haya esta pantalla en blanco durante varios segundos. Realmente queremos deshacernos de eso. Así que dijimos, ¿sabes qué? Conocemos la solución para eso. Simplemente vamos a hacer prerrenderizado en el lado del servidor. Así que ahora enviamos un HTML más grande, nota que el HTML se hizo más grande, y ahora la página no está en blanco. Es la aplicación real que tienes. Pero, ¿adivina qué? No puedes hacer clic en ella. Aparece más rápido, lo cual es genial, pero aún no puedes tener ninguna interactividad en esa página. Así que en este punto descargamos el JavaScript y ejecutamos la aplicación.

3. Reconciliación, Hidratación y Resumibilidad

Short description:

Ya no lo llamamos renderizado, ahora lo llamamos reconciliación o hidratación. La interactividad es un poco menor porque todo se desplazó. La hidratación funciona visitando todos los hijos para encontrar los escuchadores de clics. Las personas están explorando la hidratación parcial, pequeñas islas o componentes del servidor de React. La resumibilidad permite la interacción inmediata con HTML que contiene información de los escuchadores. JavaScript es más pequeño al eliminar duplicados. La aplicación se muestra más rápido y es más rápida de interactuar. En el mundo resumible, los escuchadores son clave.

Ya no lo llamamos renderizado, ahora lo llamamos reconciliación o hidratación, pero en realidad es exactamente lo mismo, simplemente estamos reutilizando los nodos del DOM. Y luego terminamos con la misma página exacta y ahora puedes hacer clic en ella. Y esto en realidad es más lento. Porque nota que todo se desplazó. Así que parece más rápido, pero la interactividad en realidad es un poco menor.

Y la razón por la que en realidad es más lento es porque estamos enviando la misma información dos veces, una vez como HTML y luego nuevamente como JavaScript. Si observas una cadena que dice, digamos, hola mundo, el hola mundo aparecerá una vez en el HTML y una vez en JavaScript. Y así es como funciona la hidratación, comienzas con el componente raíz aquí y luego visitas a todos los demás hijos y lo que realmente estás buscando son estas cajas rojas. Estas cajas rojas representan los eventos. Necesitas saber dónde están los escuchadores de clics, ¿verdad? Y esto es una gran cantidad de código para descargar y ejecutar. Y así las personas están explorando diferentes cosas. Tal vez deberíamos hacer una hidratación parcial, en lugar de tener un gran árbol, tal vez podamos tener un montón de pequeñas islas, o retrasarlo, etc. Y eso ciertamente mejora la situación, mejora. O tal vez deberíamos hacer algo como los componentes del servidor de React donde decimos que algunas de las raíces terminan en un servidor, pero los hijos seguirán estando en el mundo del cliente. Pero al final del día, lo que quieres es tener acceso a estos escuchadores. Los escuchadores son clave para hacer que tu página sea interactiva.

Así que me gustaría mostrarte un mundo alternativo, un mundo que llamo Resumibilidad. Comienzas con HTML y el HTML contiene la página, como antes. Pero hay una gran diferencia aquí, y es que esta página contiene información sobre dónde están los escuchadores. Y como resultado, puedes hacer clic de inmediato e interactuar con ella. En otras palabras, en el momento en que aparece un botón, está listo para ser clicado e interactuado. Pero aún no tienes JavaScript, así que tienes que descargarlo. Y en este caso particular, nota que el JavaScript es mucho, mucho más pequeño. ¿Por qué es eso? Bueno, ¿qué falta aquí? Lo explicaré en un segundo porque, bueno, eliminamos los duplicados. Sabemos, miramos la página y dijimos, en realidad, ese hola mundo que imprimiste, eso es estático. Nunca tendrá que volver a renderizarse en un cliente, ¿entonces por qué lo estamos enviando? ¿verdad? Y luego, por supuesto, no lo hacemos, como resultado, porque el HTML no está allí, no tenemos que ejecutar la aplicación, no tenemos que reconciliar la aplicación. Y así tu aplicación no solo se muestra más rápido, sino que es fundamentalmente más rápida de interactuar. Y así es como llamamos a la resumibilidad. Y así que la cosa es, en el mundo resumible, en lugar de comenzar en el componente raíz y luego, ya sabes, encontrar todos los escuchadores, en realidad lo volteas todo y dices, no, no, no, comienzas en los escuchadores. Y son los escuchadores los que importan porque si no hay escuchador, ese componente es inerte.

4. Optimización, Código Limpio y Magia del Compilador

Short description:

Al comenzar con los escuchadores en lugar de desde la raíz, tu aplicación se divide en fragmentos más pequeños. El código limpio es simple, mientras que el código rápido es complicado. Queremos un sistema en el que podamos escribir código limpio y permitir que la computadora lo optimice. Dos nuevos conceptos, señales y extracción de código, pueden proporcionar un rendimiento de inicio constante y carga diferida de forma predeterminada. El compilador puede optimizar el código si proporcionamos las herramientas adecuadas. Las señales y la extracción de código son partes clave. Veamos un ejemplo.

No puedes hacer realmente nada con eso. Y así, en este ejemplo particular, por ejemplo, si hago clic en este componente, veo que solo este componente en particular necesita volver a renderizarse, por lo que el resto de la página ni siquiera tiene que descargarse. Y así, la clave aquí es que al comenzar con los escuchadores en lugar de desde la raíz, tu aplicación se divide automáticamente en fragmentos más pequeños. Entonces, incluso si tienes la aplicación más complicada del mundo, si haces clic en el botón de compra, lo único que tienes que hacer es comunicarte con el carrito de compras y volver a renderizar el carrito de compras. No importa si tienes un menú complicado o un componente complicado o una forma complicada de comentar sobre el producto. Es irrelevante para lo que el usuario está tratando de lograr.

Estoy seguro de que has escuchado esto, que básicamente la optimización es la raíz de todos los males, pero ¿por qué? ¿Por qué se dice esto comúnmente? Y la razón es porque el código limpio es código simple, mientras que el código rápido es complicado. Lo que estás intercambiando cuando haces algo rápido es la simplicidad por algo complicado. Y, por supuesto, nosotros, como humanos, escribimos código principalmente para otros humanos, ¿verdad? Y lo que queremos es tener un sistema en el que pueda escribir código limpio, pero la computadora pueda optimizarlo todo por mí, ¿verdad? Quiero que la computadora haga la parte difícil y ya tenemos eso. Tenemos compiladores y linters y todo tipo de cosas mágicas y hacen todo tipo de optimizaciones para que podamos seguir viendo un código limpio y no tener que preocuparnos por las optimizaciones allí.

Entonces, ¿cómo podemos tener una aplicación así? La forma en que la mayoría de las personas construyen aplicaciones es comenzar construyendo una aplicación y luego algunos de nosotros realmente llegamos a la siguiente fase y nos damos cuenta de que nuestra aplicación es lenta. Y aún menos de nosotros realmente estamos haciendo algo al respecto, ¿verdad? Porque la optimización es difícil. La optimización no es un solo error. Es algo que se te va colando con el tiempo. Y así, la pregunta es, ¿qué podemos cambiar? ¿Qué tal si te dijera que puedes aprender dos nuevos conceptos? Un concepto es la señal. Creo que Ryan habló de eso hoy temprano. Se conoce como el CEO de la señal, y el segundo es la extracción de código y la extracción de código se denota aquí como un signo de dólar con paréntesis. ¿Qué tal si estas dos cosas permitieran que el compilador te brinde un rendimiento de inicio constante? Es decir, no importa cuán grande sea tu aplicación, siempre es un inicio de uno. Siempre hay la misma cantidad de JavaScript antes de que necesites, antes de que puedas interactuar. ¿Qué tal si puedes obtener la carga diferida de forma predeterminada sin ningún esfuerzo? ¿Y qué tal si puedes obtener la ejecución diferida sin ningún esfuerzo en absoluto? Esa es una optimización que no es prematura en el sentido de que el humano no tiene que hacerlo. El código sigue siendo limpio, pero el compilador puede hacerlo. Pero el compilador solo puede hacerlo si le damos las herramientas adecuadas. Y así, estas herramientas son importantes, y por eso las señales y la extracción de código son partes clave. Cuando le das esto al compilador, el compilador puede brindarte la mejor experiencia posible para el desarrollador, y la computadora puede optimizarlo y hacer toda esta magia de carga diferida y asegurarse de que solo se escriba la cantidad mínima de código. Esa es la teoría. Permíteme mostrarte algo en la práctica. De acuerdo. Aquí tengo un ejemplo para ti. En realidad, veamos el código primero.

5. Demostración de la Aplicación y Renderizado de Componentes

Short description:

Aquí tienes una demostración simple de una aplicación que se parece a React. Los componentes anuncian cuando se renderizan. Las demos incluyen saludo, contador, reloj y RPC.

Así que aquí tienes una aplicación simple, una demostración simple que he construido para estos propósitos. Observa que se parece mucho a React, y eso no es casualidad, es intencional. También observa que de vez en cuando hay un signo de dólar presente, y eso es básicamente lo que nos permite hacer carga diferida, extracción de código, etc. Y así que lo que he hecho es asegurarme de que cada componente anuncie cuando se renderiza. Dice `renderizando app`, o lo que sea que tengas aquí. Y luego aquí tengo saludo, contador, reloj y RPC, las diferentes demos que voy a mostrar hoy.

6. Componente Hello y Extracción de Código

Short description:

Vamos a revisar el componente hello y ver cómo funciona el sistema. Cuando se renderiza el componente, registra un mensaje y muestra un botón. Al hacer clic en el botón, se descarga el código JavaScript necesario. El sistema optimiza la descarga enviando solo el código requerido, en este caso, un registro en la consola. El service worker prepopula la caché, garantizando un rendimiento rápido y confiable incluso en redes lentas. La extracción de código permite que el sistema ejecute el código necesario importándolo en el nivel superior. Los botones pueden cerrar sobre el estado y otras variables.

Así que vamos a revisar primero el componente hello. El componente hello dice, oye, primero que nada, te voy a decir que me están renderizando, así que voy a registrar en la consola, y simplemente voy a tener un botón, y el botón va a tener un registro en la consola cuando haga clic en él, y simplemente voy a decir hello JS Nation. Así que vamos a ejecutar lo primero. Vamos a ir a nuestra aplicación. Vamos a actualizarla, y observa que no se está descargando ningún JavaScript. Estoy mirando el JavaScript, no se está descargando ningún JavaScript. Así que si voy y hago clic en hello, observa que es en ese momento cuando aparece el JavaScript y aparece hello JS Nation. Como desarrollador, he expresado mi intención. Mi intención era tener un componente con este escuchador, y el framework pudo hacer la magia. Ahora, observa lo que se descargó. Lo que se descargó fue literalmente solo console log JS Nation. Nada más. El sistema, con la ayuda de estos signos de dólar, pudo analizar todo el problema y decir, ah, solo necesitas el registro en la consola y no necesitas nada más para lograr lo que quieres. Entonces, ¿por qué estamos enviando toda la aplicación? Eso es innecesario. Solo voy a enviar lo que realmente necesitas.

Ahora, en este punto, mucha gente dirá, oye, sé lo que va a pasar. Vas a estar en una red lenta. Vas a hacer clic en algo y tendrás que esperar para siempre. Así que déjame mostrarte otro detalle importante. Esto, observa en el tamaño, sé que es difícil de ver, dice service worker. Esto fue un acierto en la caché. Así es como realmente funciona, cuando navegas a una página, el service worker se activa y comienza a descargar todo el código necesario y prepopula la caché, para que cuando hagas clic, la máquina virtual, el B8, vaya y obtenga los datos de la caché, será un acierto en la caché y, por lo tanto, no tendrás ningún tipo de retraso, incluso en redes lentas e inestables. Si cargas la página antes de entrar al túnel, la página seguirá funcionando cuando estés en el túnel.

De acuerdo, ¿cómo funciona esta magia? Bueno, resulta que el sistema puede darse cuenta de que, oye, para hacer clic en este botón, tengo que ejecutar este código. Pero el problema es, ¿cómo obtengo esto? Para que el JavaScript ejecute algún código, tiene que haber una exportación en el nivel superior. Alguien en algún lugar tuvo que hacer básicamente este fragmento de código aquí, ¿verdad? Y eso es lo que hace la extracción de código. Este signo de dólar aquí básicamente le dice al sistema, quiero que lo extraigas y lo pongas en algo de nivel superior que pueda importar. Y como ahora puedo importarlo, puede ejecutarse por sí solo sin ningún tipo de resto del sistema disponible. Pero sabes qué, dirás, bueno, sí, pero mira, este console.log no cierra sobre nada. En realidad, nuestros botones cierran sobre el estado y otras cosas.

7. Counter Example and Component Hierarchy

Short description:

Permíteme mostrarte un ejemplo ligeramente más complicado, que es el contador. Normalmente, cuando ves un contador, ves un componente único que maneja tanto los botones como la representación y el estado. Aquí, estoy dividiendo las cosas para mostrarte el poder de optimización que puede hacer QUIC. Se está renderizando el contador. Voy a crear un estado, llamado la señal, y dárselo a un incrementador, que es un botón que sabe cómo incrementar el valor. También le daré el valor al envoltorio de visualización, que sabe cómo representarlo. Por último, tenemos la visualización que muestra el contador y el incrementador, que obtiene el contador y lo incrementa.

Permíteme mostrarte un ejemplo ligeramente más complicado, que es el contador. Permíteme, voy a cambiar a otra pestaña donde se está ejecutando en modo de desarrollo porque quiero mostrarte las cosas de manera más detallada porque no necesariamente quiero mostrarte el service worker. Es la misma demostración exacta, solo que se está ejecutando en modo de desarrollo.

Observa lo que se descargó. Cuando presiono más uno, se descargó un código que realiza la incrementación, se descargó el framework y, finalmente, se descargó algo de construcción que no es realmente importante. Pero esta es la parte importante, ¿verdad? Descargué un fragmento de código que incrementó el contador. Veamos la implementación de esto. Ahora, el contador es intencionalmente bastante complicado porque quiero mostrar cosas importantes. Normalmente, cuando ves un contador, ves un componente único que maneja tanto los botones como la representación y el estado. Aquí, intencionalmente, voy a dividir las cosas porque quiero tener tantos componentes involucrados como sea posible para mostrar el poder de optimización que QUIC puede hacer.

Aquí tienes tu contador. En primer lugar, te diré que se está renderizando el contador. Voy a crear un estado, y en este caso en QUIC se llama la señal, y lo que voy a hacer es tomar la señal y dársela a un incrementador, que básicamente es solo un botón que sabe cómo incrementar el valor, y voy a dar el valor al envoltorio de visualización, que nuevamente sabe cómo representarlo. La razón por la que lo divido es para mostrarte una jerarquía de componentes. Así que lo estoy complicando un poco más. El envoltorio de visualización realmente no hace nada. Simplemente toma el valor y lo pasa a la visualización. Lo que quiero mostrar aquí es un ejemplo típico de prop drilling. Un componente que por sí mismo no hace nada útil. Solo pasa el valor hacia abajo. Y finalmente tenemos la visualización que muestra el contador, y tenemos nuestro incrementador que es solo un botón y obtiene el contador y hace count.value++. Sé que está demasiado simplificado, pero fundamentalmente eso es lo que es una aplicación web. Tienes un lugar donde guardas tu estado, tienes un lugar donde muestras el estado, tienes un lugar donde mutas el estado y probablemente tienes un montón de componentes no relacionados que solo hacen prop drilling para obtener la interfaz de usuario que deseas. Ahora, cuando esto sucede en el mundo normal y modificas el contador, si esperas que todos estos registros en la consola se vuelvan a ejecutar y se vuelvan a representar y se vuelvan a imprimir. Permíteme mostrarte lo que realmente sucede aquí. Así que presionemos más uno. Observa que funcionó. Sumó uno. Lo que descargamos fue solo este escuchador, ¿verdad? Solo este fragmento de código aquí. Solo esto.

8. Framework, Signals, and DOM Connection

Short description:

El framework solo envía el código necesario para la mutación al cliente, mientras que el resto es ruido innecesario. Las señales permiten una conexión directa al DOM, por lo que el servidor aprende las relaciones entre los componentes y actualiza el DOM en consecuencia. El código irrelevante no se envía al cliente.

Nada más. Luego apareció el framework. Y, por supuesto, este archivo de construcción no es importante. Observa lo que no apareció. Ninguno de los componentes apareció. ¿Verdad? El hecho de que un estado estuviera en un componente y que hiciéramos prop drilling, etc., en la consola no hay nada aquí, y también dentro del código fuente, ni siquiera nos molestamos en enviarlo. En realidad, lo único que enviamos fue este fragmento de código que fue lo que hizo la mutación. Todo lo demás es innecesario. ¿Por qué? Porque las señales te permiten conectarte directamente al DOM. Cuando este fragmento de código se ejecuta en un servidor, el servidor aprende sobre la relación de los componentes, y aprende que, por ejemplo, esta señal está conectada a esta parte del DOM aquí. Entonces, cuando incremento este valor, realmente solo tengo que incrementar, ya sabes, actualizar el DOM aquí, y todo lo demás es irrelevante. Es solo ruido. Y enviarlo al cliente sería problemático. Por lo tanto, no se envía.

9. Clock, UseVisible, and Quick Loader

Short description:

¿Qué pasa si tengo un reloj que solo aparece cuando lo desplazas? El reloj funciona con JavaScript. Hay una tarea useVisible que se ejecuta cuando el componente se vuelve visible. Si el componente es invisible, no es necesario descargar ni ejecutar nada. Otra cosa interesante es la capacidad de realizar un trabajo costoso en el servidor mientras el cliente maneja el valor de retorno. Esto muestra un modelo de ejecución unificado. ¿Es un botón inmediatamente clickable? Hay un pequeño cargador rápido que configura un oyente global, lo que hace que el botón sea clickable sin demora.

De acuerdo. Permíteme mostrarte algo más. ¿Qué pasa si tengo un reloj? Un reloj solo aparece cuando lo desplazas. Observa que el reloj está en funcionamiento. Permíteme mostrártelo de nuevo. No tengo JavaScript, desplaza el reloj a la posición, cuando el reloj aparece, el JavaScript aparece y comienza a funcionar.

¿Qué hace exactamente el reloj? Bueno, hay una tarea useVisible que puedes pensar como useEffect. UseEffect se ejecuta en la hidratación, pero no hay hidratación, entonces, ¿cuándo se supone que debemos ejecutar algo así? Bueno, la respuesta es que se ejecuta cuando el componente se vuelve visible. Este fragmento de código hace naturalmente lo que esperarías, pero tiene un comportamiento interesante adicional que es como, oye, si el componente es invisible, ¿por qué molestarse en descargar, ejecutar o hacer algo así?

Permíteme mostrarte una cosa más interesante. Aquí tenemos un botón que dice Hacer algo, y voy a cambiar a la consola de registro. Este Hacer algo dice que voy a hacer un trabajo, un trabajo costoso, y devolver algún valor. Permíteme mostrártelo aquí. Hay un componente RPC que dice renderizar, un botón de clic que dice oye, voy a hacer el trabajo, voy a crear una fecha y voy a crear una función que dice hacer trabajo, y voy a fingir que este es el trabajo costoso, y, solo por diversión, voy a devolver una función que en realidad tiene un valor. Cosas típicas que haces, devuelves cierres y pasas cosas, ¿verdad? Obviamente, todo esto sucede en el navegador porque, bueno, está en el navegador. Pero ¿qué pasa si puedo hacer magia loca como esta, decir servidor, y de repente, si actualizo, y hago clic en el botón, nota que el clic fue en un cliente, el valor de retorno está en un cliente, pero el trabajo costoso, bueno, eso apareció en un servidor. Eso es bastante mágico cuando puedes hacer eso. Una de las cosas de las que hablamos en Click es la idea de un modelo de ejecución unificado, y puedo mostrarte más de eso más adelante. ¿Y dónde están mis diapositivas? Mis diapositivas desaparecieron. Aquí están. De todos modos, eso es más o menos mi charla. Espero que lo hayas disfrutado y espero que hayas entendido el punto, y si tienes alguna pregunta, estaré encantado de responder.

Aquí hay una pregunta filosófica. ¿Es un botón inmediatamente clickable? ¿Necesita descargar un pequeño fragmento de JavaScript primero, verdad? Sí, esa es una buena pregunta. Entonces hay algo llamado un cargador rápido. Un cargador rápido es muy pequeño, alrededor de un kilobyte, y se ejecuta en aproximadamente un milisegundo en una computadora de escritorio y alrededor de 10 milisegundos en un dispositivo móvil. Y todo lo que hace es configurar un oyente global. Y así, esa etiqueta de script se incluye en el HTML para que sea inmediato. Y en ese punto, no sucede nada más. Entonces, cuando haces clic en un botón, el evento se propaga hacia arriba y el oyente global de nivel superior lo captura , mira el botón y ve que el botón tiene un atributo, y el atributo dice algo como en dos puntos clic igual y tiene una URL, y ahí es donde va y obtiene el código. Y sabemos que esa URL realmente causará un acierto en la caché.

10. JavaScript Loading and Interactions

Short description:

Entonces, los datos están disponibles de inmediato, lo que los hace clicables. Las animaciones pesadas se cargan a medida que te desplazas, mejorando el rendimiento. Las interacciones se priorizan, reduciendo los retrasos. Qwick supera a las aplicaciones de hidratación. El service worker no precarga todo.

Entonces, los data estarán disponibles de inmediato. Y por lo tanto, podemos ejecutarlos de inmediato. Gracias. Quiero decir, obviamente, un botón es inmediatamente clicable. Un botón HTML se puede hacer clic. No hará nada hasta que se cargue el JavaScript. Bueno, el punto es que no hay un estado en el que tengas un botón que puedas hacer clic y el En todos los puntos, en el momento en que el botón es visible, se puede hacer clic y se garantiza que se procesará.

La siguiente pregunta es, ¿hay alguna forma de solucionar el problema de carga de JavaScript con animaciones pesadas que comienzan de inmediato en la página de carga? Entonces, el ejemplo del reloj fue un ejemplo de eso, ¿verdad? Porque decía, cuando sea visible, quiero que comiences a ejecutar este código de manera ansiosa. Y así, cuando sea visible, puedes comenzar a ejecutar animaciones o cualquier cosa de ese tipo de manera ansiosa. Así que eso es ciertamente posible. Y de hecho, tenemos un par de sitios web que están construidos con Qwick, y lo bueno de ellos es que tienen muchas animaciones pesadas, y a medida que te desplazas, porque es un sitio web largo, más y más animaciones comienzan a cargarse o transmitirse a la aplicación, a medida que te desplazas hacia la parte inferior. Entonces, la animación que actualmente no es visible no se carga. Pero luego, cuando se vuelve visible, se carga automáticamente y comienza a ejecutarse.

Eso responde perfectamente a la siguiente pregunta. ¿Cómo funciona eso si la página tiene muchas interacciones? ¿Se descargará cada pequeña pieza al hacer clic, lo que resultará en muchos archivos pequeños? Esa también es una muy buena pregunta. Entonces, cuanto más complicada se vuelve tu aplicación, más interacciones tienes, mejor funcionará Qwick, en realidad. La forma en que se resuelve esto es que cuando ejecutas una aplicación, puedes observar el comportamiento del usuario en el mundo real y puedes ver que estos botones se hacen clic con más frecuencia que estos otros. Y luego, lo que puedes hacer es ir al bundler y simplemente darle una lista de símbolos y decir, oye, quiero asegurarme de que todos estos símbolos, que básicamente son estas funciones cargadas de forma diferida, estén juntas en un solo fragmento. Y luego, el service worker sabe que puede descargarlos en órdenes específicas. Por lo tanto, descarga el fragmento de alta prioridad primero. Para que los botones que es más probable que se hagan clic estén disponibles de inmediato primero. Y luego comienza a descargar todas las demás partes con el elemento de menor prioridad en la parte inferior, aunque todo se descarga de manera ansiosa. El resultado será que si haces clic en un botón en el que es más probable que hagas clic , casi no habrá ningún retraso. Y en todos los casos, perdón, solo para ser claro, en todos los casos, el retraso hasta la interactividad siempre será mejor que una aplicación de hidratación equivalente. Como no puedes estar en esta hidratación, siempre tendrás más cosas para descargar y más cosas para ejecutar que una interfaz de usuario equivalente y razonable.

Tal vez la audiencia holandesa se ponga un poco más gruñona después de la cena, pero hay algunas preguntas bastante complicadas aquí, así que no me culpes. Soy solo un medio. Si el service worker precachea todo para evitar el bloqueo, ¿cómo es mejor que cargar todo el JavaScript junto? Otra buena pregunta. Bien, el service worker en realidad no precachea todo. Lo que sucede cuando ejecutas una aplicación es que te das cuenta de que muchas cosas en realidad nunca se ejecutan en el cliente.

11. Service Worker and Component Downloads

Short description:

El service worker solo descarga los componentes con los que el usuario puede interactuar, reduciendo significativamente la cantidad de código. Los componentes no interactivos no son descargados por el service worker.

Entonces, como les he mostrado la aplicación, no había nada que el usuario pudiera haber hecho para forzar la descarga de muchos de estos componentes. Puedes observar eso, y esa información luego se alimenta al service worker, y por lo tanto, el service worker solo descargará cosas que haya visto que era posible descargar en el desarrollo. En la peor situación posible, el service worker tendría que descargar todo, que es lo que ya estás haciendo con la hidratación. En la gran mayoría de los casos, el service worker terminará descargando significativamente menos, como una orden de magnitud menos de código. Porque la mayoría de los componentes que tienes en realidad no son interactivos, solo están ahí con fines de diseño. Y debido a que no son interactivos, no hay forma de que un escucha de clic o cualquier tipo de interactividad pueda hacer que se vuelvan a renderizar y como resultado, el service worker no los descarga.

12. Error Code in Quick and SEO

Short description:

¿Qué es el código de error seis en Quick? ¿Quick es compatible con los componentes web? Quick puede reanudar porque el servidor entrega HTML, lo que hace posible el SEO.

Aquí hay una pregunta que no significa nada para mí, pero está ahí. De acuerdo, adelante. ¿Qué es el código de error seis en Quick? Ya lo he tenido un par de veces. No tengo idea. Pero está bien porque alguien lo está usando. Perfecto. Me encanta. Lo buscaré. Entonces, si tienes, quiero decir, obviamente nunca tengo errores en mi código, pero si tienes el error seis, ni siquiera este tipo sabe lo que significa. Así que es tu culpa. Mala suerte.

¿Quick es compatible con los componentes web? Sí, Quick tiene lo que llamamos Quickify y en Quickify, por ejemplo, puedes tomar componentes existentes de React y ejecutarlos en Quick. Olvidé mencionarlo en el escenario. Entonces, en realidad puedes ejecutar componentes existentes de React dentro de Quick. De la misma manera, podrías hacer un Quickify para los componentes web. Ya tenemos adaptadores para, ya sabes, Views, Solid y otros frameworks populares. Así que también podríamos tener, en teoría, componentes web. Lo difícil de los componentes web es que no tienen realmente una buena historia de renderizado en el lado del servidor. Y como resultado, Quick vive del hecho de que el HTML entregado desde el servidor ya tiene todo presente. Y debido a que los componentes web no tienen una buena forma de pre-renderizarlo en el contexto de Quick, no es realmente la mejor opción. Aún puedes hacerlo en el sentido de que puedes hidratar ansiosamente los componentes web en el cliente en el renderizado inicial. Pero nuevamente, estamos volviendo al mundo de la hidratación.

En un tema relacionado o sospecho que está relacionado, dado que todo aparece solo cuando es necesario, ¿cómo se relaciona eso con el maravilloso mundo del SEO? Me refiero, por supuesto, a los optimistas de los motores de búsqueda. Sí, no. El SEO es en realidad algo perfecto para Quick porque si deshabilitas JavaScript en un sitio de Quick , básicamente estás viendo lo que ve el SEO. Puedes ver eso. Te invito a ir a quick.builder.io y navegar por ese sitio con JavaScript deshabilitado, y verás eso. El SEO en realidad ve prácticamente todo. La razón por la que Quick puede reanudar es porque el servidor entrega HTML. El hecho de que el servidor entregue el HTML es exactamente lo mismo que hace posible el SEO.

13. SEO, Debugging, and Framework Comparison

Short description:

El SEO es crucial para la reanudabilidad de Quick. Quick admite tanto SSR como SSG almacenando HTML en un CDN. La depuración en Quick funciona como se espera con mapas de origen y puntos de interrupción. QUIC es una reevaluación fundamental de los marcos web, centrándose en la reanudabilidad. Otros marcos como Marco y Wiz también adoptan esta idea, con Wiz impulsando la Búsqueda de Google y Google Fotos. Estos marcos priorizan la interactividad y la ejecución perezosa del código.

SEO es realmente algo en lo que Quick se basa porque sin eso, la reanudabilidad realmente no es posible. Solo para señalar, puedes almacenar el HTML en un CDN, por lo que Quick no solo puede hacer SSR, también puede hacer SSG. Por lo tanto, ambos escenarios son perfectamente posibles.

Bueno, esta es una pregunta interesante que no se me había ocurrido. Así que gracias, Ben, quienquiera que seas. Y esta es probablemente la última pregunta, pero estoy seguro de que puedes encontrar a Mishko y tener una... Me encantan las preguntas. Puedes venir a hablar conmigo después. Tengo pegatinas. Sí, preguntas... Así que realmente tenemos muchas preguntas geniales. Genial. Pero esta es interesante. ¿Qué pasa con la depuración? Si el JavaScript se descarga solo a pedido, ¿qué pasa con los puntos de interrupción y las funciones del depurador, cómo funcionan? Funciona como esperarías. Tenemos mapas de origen. Obviamente no puedes colocar un punto de interrupción hasta que se descargue el JavaScript. Por lo general, la forma de resolver esto es hacer clic en un botón primero y luego colocar el punto de interrupción y luego actualizar el navegador y ahora tienes el punto de interrupción adecuado en ese sentido. Es posible que debas colocar puntos de interrupción en el lado del servidor, porque, bueno, es un modelo de ejecución del servidor y del cliente. Por lo tanto, debes estar familiarizado con cómo funciona la depuración tanto en Node.js como en el navegador. Pero al final del día, tienes mapas de origen y parece código regular y colocas puntos de interrupción y en su mayor parte, es como una cosa normal.

Soy notoriamente escéptico sobre los últimos y mejores frameworks, pero en realidad esto suena tan emocionante que voy a echarle un vistazo. Creo, quiero decir, sé que soy parcial porque es, ya sabes, mi creación y siempre amas a tus creaciones, pero creo que QUIC es una reevaluación fundamental de lo que es un marco web. Sabes, todos los marcos que existen realmente hacen hidratación. Bueno, debería decir todos, pero hay pocos. Ebay tiene esta cosa llamada Marco. Marco también tiene reanudabilidad y internamente Google tiene un proyecto llamado Wiz y Wiz es un marco que alimenta internamente la Búsqueda de Google y Google Fotos y una cosa que puedes decir sobre la búsqueda es que es rápida y nunca tienes que esperar a que la Búsqueda de Google sea lenta en términos de interactividad. Y antes de que digas algo como, bueno, la Búsqueda de Google no es complicada, ¿has intentado poner una película y obtener un carrusel o poner una ecuación y obtener un gráfico o una calculadora de ella. Así que en realidad hay mucha interactividad que Google puede hacer y está impulsada por Wiz y si bien Wiz no es exactamente lo mismo que QUIC, tiene la misma idea exacta de no comenzar con la hidratación, en su lugar, solo dejemos algunos marcadores en el HTML para que cuando interactúes, solo entonces se ejecute el código de forma perezosa. Brillante. Damas, amigos, romanos y ECMAScriptors, aplaudan a Mischko.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

A Guide to React Rendering Behavior
React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Compiler - Understanding Idiomatic React (React Forget)
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
Top Content
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
Speeding Up Your React App With Less JavaScript
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
Top Content
Too much JavaScript is getting you down? New frameworks promising no JavaScript look interesting, but you have an existing React application to maintain. What if Qwik React is your answer for faster applications startup and better user experience? Qwik React allows you to easily turn your React application into a collection of islands, which can be SSRed and delayed hydrated, and in some instances, hydration skipped altogether. And all of this in an incremental way without a rewrite.
React Concurrency, Explained
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
Top Content
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
From GraphQL Zero to GraphQL Hero with RedwoodJS
GraphQL Galaxy 2021GraphQL Galaxy 2021
32 min
From GraphQL Zero to GraphQL Hero with RedwoodJS
Top Content
We all love GraphQL, but it can be daunting to get a server up and running and keep your code organized, maintainable, and testable over the long term. No more! Come watch as I go from an empty directory to a fully fledged GraphQL API in minutes flat. Plus, see how easy it is to use and create directives to clean up your code even more. You're gonna love GraphQL even more once you make things Redwood Easy!
The Future of Performance Tooling
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
Top Content
Our understanding of performance & user-experience has heavily evolved over the years. Web Developer Tooling needs to similarly evolve to make sure it is user-centric, actionable and contextual where modern experiences are concerned. In this talk, Addy will walk you through Chrome and others have been thinking about this problem and what updates they've been making to performance tools to lower the friction for building great experiences on the web.

Workshops on related topic

React Performance Debugging Masterclass
React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Top Content
Featured WorkshopFree
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React at Scale with Nx
React Summit 2023React Summit 2023
145 min
React at Scale with Nx
Top Content
Featured WorkshopFree
Isaac Mann
Isaac Mann
We're going to be using Nx and some its plugins to accelerate the development of this app.
Some of the things you'll learn:- Generating a pristine Nx workspace- Generating frontend React apps and backend APIs inside your workspace, with pre-configured proxies- Creating shared libs for re-using code- Generating new routed components with all the routes pre-configured by Nx and ready to go- How to organize code in a monorepo- Easily move libs around your folder structure- Creating Storybook stories and e2e Cypress tests for your components
Table of contents: - Lab 1 - Generate an empty workspace- Lab 2 - Generate a React app- Lab 3 - Executors- Lab 3.1 - Migrations- Lab 4 - Generate a component lib- Lab 5 - Generate a utility lib- Lab 6 - Generate a route lib- Lab 7 - Add an Express API- Lab 8 - Displaying a full game in the routed game-detail component- Lab 9 - Generate a type lib that the API and frontend can share- Lab 10 - Generate Storybook stories for the shared ui component- Lab 11 - E2E test the shared component
Building WebApps That Light Up the Internet with QwikCity
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
Miško Hevery
Miško Hevery
Building instant-on web applications at scale have been elusive. Real-world sites need tracking, analytics, and complex user interfaces and interactions. We always start with the best intentions but end up with a less-than-ideal site.
QwikCity is a new meta-framework that allows you to build large-scale applications with constant startup-up performance. We will look at how to build a QwikCity application and what makes it unique. The workshop will show you how to set up a QwikCitp project. How routing works with layout. The demo application will fetch data and present it to the user in an editable form. And finally, how one can use authentication. All of the basic parts for any large-scale applications.
Along the way, we will also look at what makes Qwik unique, and how resumability enables constant startup performance no matter the application complexity.
Next.js 13: Data Fetching Strategies
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
Top Content
WorkshopFree
Alice De Mauro
Alice De Mauro
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Performance Debugging
React Advanced Conference 2023React Advanced Conference 2023
148 min
React Performance Debugging
Workshop
Ivan Akulov
Ivan Akulov
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
Hard GraphQL Problems at Shopify
GraphQL Galaxy 2021GraphQL Galaxy 2021
164 min
Hard GraphQL Problems at Shopify
WorkshopFree
Rebecca Friedman
Jonathan Baker
Alex Ackerman
Théo Ben Hassen
 Greg MacWilliam
5 authors
At Shopify scale, we solve some pretty hard problems. In this workshop, five different speakers will outline some of the challenges we’ve faced, and how we’ve overcome them.

Table of contents:
1 - The infamous "N+1" problem: Jonathan Baker - Let's talk about what it is, why it is a problem, and how Shopify handles it at scale across several GraphQL APIs.
2 - Contextualizing GraphQL APIs: Alex Ackerman - How and why we decided to use directives. I’ll share what directives are, which directives are available out of the box, and how to create custom directives.
3 - Faster GraphQL queries for mobile clients: Theo Ben Hassen - As your mobile app grows, so will your GraphQL queries. In this talk, I will go over diverse strategies to make your queries faster and more effective.
4 - Building tomorrow’s product today: Greg MacWilliam - How Shopify adopts future features in today’s code.
5 - Managing large APIs effectively: Rebecca Friedman - We have thousands of developers at Shopify. Let’s take a look at how we’re ensuring the quality and consistency of our GraphQL APIs with so many contributors.