Depuración del Rendimiento de React

Rate this content
Bookmark

Los primeros intentos de Ivan en la depuración de rendimiento fueron caóticos. Veía una interacción lenta, probaba una optimización aleatoria, veía que no ayudaba, y seguía probando otras optimizaciones hasta que encontraba la correcta (o se rendía).


En aquel entonces, Ivan no sabía cómo usar bien las herramientas de rendimiento. Hacía una grabación en Chrome DevTools o React Profiler, la examinaba, intentaba hacer clic en cosas al azar, y luego la cerraba frustrado unos minutos después. Ahora, Ivan sabe exactamente dónde y qué buscar. Y en esta masterclass, Ivan te enseñará eso también.


Así es como va a funcionar. Tomaremos una aplicación lenta → la depuraremos (usando herramientas como Chrome DevTools, React Profiler, y why-did-you-render) → identificaremos el cuello de botella → y luego repetiremos, varias veces más. No hablaremos de las soluciones (en el 90% de los casos, es simplemente el viejo y regular useMemo() o memo()). Pero hablaremos de todo lo que viene antes - y aprenderemos cómo analizar cualquier problema de rendimiento de React, paso a paso.


(Nota: Esta masterclass es más adecuada para ingenieros que ya están familiarizados con cómo funcionan useMemo() y memo() - pero quieren mejorar en el uso de las herramientas de rendimiento alrededor de React. Además, cubriremos el rendimiento de interacción, no la velocidad de carga, por lo que no escucharás una palabra sobre Lighthouse 🤐)

148 min
31 Oct, 2023

AI Generated Video Summary

Esta masterclass sobre la Depuración del Rendimiento de React cubre varios temas como el análisis del rendimiento con Chrome DevTools y React Profiler, la optimización de componentes para mejorar el rendimiento, y la depuración de problemas de rendimiento con herramientas como Why Did You Render y console.time. También enfatiza la importancia de priorizar el rendimiento y fomentar una cultura orientada al rendimiento dentro de los equipos de desarrollo. La masterclass concluye con ideas sobre la monitorización y optimización del rendimiento de React, incluyendo los desafíos con las bibliotecas de terceros y las limitaciones del compilador React Fiber.

1. Introducción al Taller de Depuración de Rendimiento de React

Short description:

Bienvenidos a nuestro Taller de Depuración de Rendimiento de React. Cubriremos 3 partes, centrándonos en el perfilador indirecto de ChromDevTools, una aplicación del mundo real con código complejo y efectos de depuración. Comencemos observando una aplicación lenta. Al editar muchos nodos, la aplicación se vuelve muy lenta. Podemos usar DevTools para ver cuándo la aplicación es rápida o lenta. El panel de velocidad de cuadros se llena de rojo al escribir en el editor, indicando un problema de rendimiento.

Bienvenidos a todos. Bienvenidos a todos a nuestro Taller de Depuración de Rendimiento de React. Muchas gracias por venir. Estoy emocionado de verlos a todos aquí.

Pasemos a lo importante. Entonces hola, bienvenidos a todos. Soy Ivan Akulov, soy un experto en desarrollo de Google, soy un ingeniero de rendimiento web, he estado trabajando en rendimiento durante cinco o seis años, he trabajado con empresas como Framer, Google, CNBC, etc., y hoy, vamos a hablar sobre la Depuración de Rendimiento de React.

Antes de empezar, un poco de la logística del taller. Así que tendríamos un descanso de 10 minutos, el taller dura tres horas. Y tendríamos descansos de 10 minutos cada hora. Al final, tendríamos un poco de tiempo para preguntas y respuestas. Así que si tienen alguna pregunta relacionada con el rendimiento en general, o sobre el taller específicamente, no duden en guardarlas para el final. Si tienen alguna pregunta durante el proceso del taller, no duden en escribirlas en el chat y yo las veré y les responderé. Y si hacen clic en- o obviamente no pueden hacer clic en esto. Si siguen este enlace, déjenme enviar este enlace a los chats. Si siguen este enlace, https://bit.ly. Notas de Reaperf. Encontrarán un documento de Google que les permite tomar notas colaborativas. Así que si son el tipo de persona que tiende a tomar notas durante el taller, no duden en hacerlo allí. De esta manera podrán tomar notas. Todos los demás tomarán notas. Al final, tendrán notas super detalladas de todos. Es como el comunismo. Pero sin las malas partes. ¿Es este un chiste apropiado? Espero que sea un chiste apropiado. Lo siento. En fin. Si siguen ese enlace, encontrarán un documento de Google y también encontrarán el repositorio de GitHub. Entonces... Ya lo tengo clonado. No duden en ejecutar Yarn y Yarn Start para trabajar en las mismas aplicaciones en las que estaremos trabajando. Muy bien. Estoy saltando demasiado. Ah. Sí. Vale. Y... Con todo lo relacionado con el taller hecho, comencemos.

Entonces, tendríamos 3 partes en el taller de hoy. Tendríamos 3 ejemplos. Tendríamos 3 interacciones lentas en las que trabajaremos, que estaremos depurando hoy. En la primera, nos centraremos solo en el perfilador indirecto de ChromDevTools. La segunda interacción durante la segunda parte del taller, veremos el mundo real, una gran aplicación del mundo real con mucho código y mucha complejidad. Aprenderíamos sobre ydtRender, aprenderíamos sobre cómo coinciden los hooks que desencadenan algunos renders con el código porque esto es sorprendentemente complicado en grandes aplicaciones. En la tercera parte del taller, veríamos la depuración de efectos, veríamos algunos desafíos de Rex 1517 con el perfilador, y echaríamos un vistazo a dos herramientas más como useRateAgeUpdates y Console.Loc. Para empezar, para empezar con la primera parte, echemos un vistazo a una aplicación lenta. Entonces, si clonan el repositorio, y si entran en el repositorio, encontrarán dos aplicaciones en este repositorio. Ahora, si entran en la aplicación de nodos, si instalan las dependencias, y ejecutan yarn start, obtendrán esta linda pequeña aplicación que les permite mantener nodos escritos y marcados hacia abajo. Es una aplicación muy básica. Bien, podría crear un nodo, podría escribir algo de texto, podría crear más nodos, podría crear cien nodos a la vez, por alguna razón es un nodo extraño aplicación. Y, aquí hay algo sobre esta aplicación, aquí hay una interacción particularmente lenta. Entonces, digamos que soy el desarrollador de esta aplicación, y un gerente de producto o un usuario viene a mí y dice, oye, mira, tenemos una queja. Cuando un usuario tiene muchos nodos, y trata de editar cualquiera de los nodos que tiene, lo que sucedería es que editar cualquiera de los nodos que tienen sería muy, muy lento. Y entonces, tú como desarrollador, vas a la aplicación, creas unos cientos de nodos, 700 nodos intentas escribir en el editor y te das cuenta de que escribir en el editor, efectivamente, se siente lento. Y ustedes, gente del otro lado de la pantalla, realmente no pueden ver esto, ¿verdad? Porque soy yo quien está escribiendo. Soy yo quien siente que escribo la letra y luego tarda como medio segundo en que la letra aparezca realmente en la pantalla. Pero aquí hay un truco realmente útil que me gusta usar para ver cuándo la aplicación es rápida o la aplicación es lenta. Entonces, si abro DevTools, si abro mis DevTools, y hago clic en el menú kebab, y hago clic en Más Herramientas, y hago clic en Renderización, podré desplazarme hacia abajo y hacer clic en la casilla que dice Estadísticas de Renderización de Cuadros. Y si habilito esto, si abro Más Herramientas, si abro Renderización, y si habilito Frame veré esta pequeña superposición, pequeña superposición en la parte izquierda de la pantalla que me muestra cuándo la aplicación está inactiva, o cuándo la aplicación está ocupada haciendo algo. Entonces, en este momento, si intento mover mi ratón sobre los botones de los nodos, sobre todos estos botones en la parte superior de los nodos, verán que la aplicación es rápida. Si intento desplazarme hacia abajo, verán que la aplicación es rápida. Aquí el azul significa que la aplicación está inactiva. El amarillo o el rojo significa que la aplicación está ocupada haciendo algún trabajo. Y la tasa de fps muestra con qué frecuencia se actualiza la aplicación. Estoy haciendo cosas y la aplicación es rápida. Pero si abro cualquiera de los nodos, y si intento escribir en cualquiera de los nodos, verán cómo el panel de velocidad de cuadros comienza a llenarse de rojo. Y cuanto más letras escribo, más teclas presiono a la vez, más se llena de rojo. Esto significa que la aplicación es lenta, y esto significa que el navegador está ocupado haciendo algo cuando estoy escribiendo en el editor. Muy bien. Entonces tenemos un problema de rendimiento.

2. Analizando el Rendimiento con Chrome DevTools

Short description:

Escribo en el editor y noto que la aplicación es lenta. Abro Chrome DevTools, habilito la limitación de CPU y grabo un rastro de rendimiento mientras escribo. La fila de CPU muestra cuándo la aplicación está ocupada, y veo tres picos de actividad de JavaScript correspondientes a mis interacciones. Emparejo la fila de CPU con la aplicación y paso el cursor sobre los picos para ver capturas de pantalla concretas. Amplío un pico de JavaScript, cambio al panel principal y analizo las tareas desencadenadas por el evento de pulsación de tecla. Me centro en las cosas grandes como las llamadas a funciones y sus orígenes en el desarrollo de Ragdoll.

Estoy escribiendo en el editor y la aplicación se siente lenta. Ahora, siempre que tengo un problema de performance, cualquier tipo de problema de performance, lo que siempre hago es abrir Chrome DevTools, voy al panel de performance, habilito la limitación de CPU porque las laptops de los desarrolladores, nuestras laptops son rápidas, y las laptops o teléfonos de nuestros usuarios no lo son. Así que habilito una desaceleración de CPU 4x y luego intento escribir en el editor mientras grabo un rastro de performance. Así que hago clic en grabar y escribo en el editor. Presiono una tecla y espero un poco. Presiono otra tecla y espero un poco. Quizás presiono una tecla más y espero un poco, y luego hago clic en iniciar.

Entonces, una vez que completo eso, lo que hago, lo que obtengo es una grabación de todo lo que sucedió en la aplicación mientras estaba interactuando con la aplicación. Y si estás viendo esto por primera vez, esto podría parecer bastante abrumador. Hay muchas pinturas aquí, y hay muchas cosas sucediendo aquí. Hay muchas cosas que mirar. Pero eso está bien, porque en realidad las únicas dos o tres pinturas que necesitamos mirar, las únicas dos o tres partes de la grabación que necesitamos mirar, son la fila de CPU y el panel principal.

Entonces, la fila de CPU, lo primero que hago cuando obtengo la grabación de performance es mirar la fila de CPU. La fila de CPU me muestra cuándo la aplicación estaba ocupada. Si la fila de CPU está vacía, eso significa que la aplicación estaba inactiva. Si la fila de CPU está llena de algún color, eso significa que la aplicación estaba ocupada haciendo algo. El amarillo, en este caso, significa JavaScript. También podría ser verde o violeta. Eso significa pintura o cálculos de estilo de diseño. El gris significa algún otro trabajo que está sucediendo principalmente dentro de las partes internas del navegador. Entonces, obtengo la fila de CPU y en la fila de CPU, podría ver inmediatamente cuándo exactamente la aplicación estaba ocupada. Entonces, veo que escribí en el editor tres veces y obtengo tres picos de actividad de JavaScript que, cada uno de ellos tomó tal vez un segundo, tal vez dos segundos. Todavía no lo sé. Lo ampliaremos y lo averiguaremos más tarde. Y también obtuve un pico de algo poco claro en el principio. Y entonces, este es mi primer paso. Grabo el rastro de performance y miro la fila de CPU y encuentro cuándo exactamente mi aplicación estaba ocupada. Y entonces, el siguiente paso, para mí, es averiguar cuál de estos picos corresponde a mis interacciones reales en la aplicación. Porque también podría ser que la aplicación obtenga algún temporizador que se activa, o la aplicación obtenga alguna respuesta de red que llega, y luego la aplicación haría un montón de trabajo porque la respuesta de red llegó, porque el temporizador se activó, no porque escribí en el editor, ¿verdad? Entonces, paso uno, mirar la fila de CPU. Paso dos, emparejar lo que está sucediendo en la fila de CPU con lo que está sucediendo en la aplicación. Y para esto, lo que hago es pasar el cursor sobre la fila de CPU y mirar a través de estas capturas de pantalla concretas que me muestran cómo exactamente la aplicación se veía en cualquier momento dado en el tiempo. Entonces, veamos, veamos el primer pico de CPU. Entonces aquí está el pico de CPU y estoy pasando el cursor sobre él y realmente no está sucediendo nada en la aplicación. Ves que el TextEditor aquí, no recibe ninguna nueva letra. Las dos últimas letras en el TextEditor son FG. Espero que puedas ver esto a través de la compresión de video de Zoom, pero no está sucediendo nada en la aplicación. Ahora, a medida que muevo mi ratón más allá, llego al primer pico de CPU, y veo que después del pico de CPU, el TextEditor recibe una nueva letra. Esto significa que escribí y que la escritura correspondía al primer pico. Veamos qué sucede a continuación. Paso el cursor sobre esto, miro esto, y veo que se agrega otra letra. Así que aquí era solo F, y aquí es F-E. Puedes ver que se está agregando un carácter más. Así que este fue otro momento en que escribí, aparentemente. Y veamos más adelante, así que la misma imagen aquí. El pico de CPU terminó, y una nueva letra apareció en la pantalla. Entonces, lo que esto significa es que tengo cuatro picos, y de estos cuatro picos, tres picos corresponden a mi interacción concreta de escribir en la página. Así que ese fue el segundo paso. El tercer paso que hago es, amplío cualquiera de estos picos de JavaScript, y cambio al panel principal, y miro a través del panel principal para tratar de entender todo lo que sucedió durante el pico de CPU. Muy bien, entonces echemos un vistazo. Aquí está el pico de CPU. Corresponde a esta tarea, no necesariamente una tarea de JavaScript, solo una tarea, lo que significa que el navegador estaba ocupado haciendo algo que tomó 900 milisegundos. Ahora, si bajo en la tarea, vería que la tarea se activó debido al evento de pulsación de tecla. El evento de pulsación de tecla desencadenó el evento de entrada de texto, el evento de entrada de texto desencadenó el evento de entrada. El evento de entrada a su vez, si amplío, vería que se divide en dos rectángulos, lo que significa que desencadenó dos cosas. Una de ellas es la llamada a la función. Desencadenó alguna llamada a la función. Y otra de ellas es el rectángulo runMicroTasks. Entonces, por defecto, siempre que veo alguna tarea que se divide en una tarea más pequeña, simplemente elijo la tarea más grande y empiezo a bajar. Mi tarea, mi objetivo en este momento no es entender todo lo que está sucediendo en esta tarea, sino formar una imagen de alto nivel de, bien, ¿en qué exactamente está gastando la aplicación la mayor parte del tiempo, verdad? Así que solo me voy a centrar en las cosas grandes. Entonces, pulsación de tecla, entrada de texto, entrada, runMicroTasks. Luego obtengo alguna llamada a la función. Y luego, después de la llamada a la función, en realidad empiezo a obtener algunos rectángulos que tienen un color diferente y que tienen, que tienen nombres diferentes. Y todos estos rectángulos son llamadas a funciones. Así que esta es una función anónima que fue llamada desde el desarrollo de Ragdoll. Esta es una función flushSyncCallback que se llama desde el desarrollo de Ragdoll. Así que la función flushSyncCallback llamó a performSyncWorkOnRoot, que nuevamente proviene del desarrollo de Ragdoll, performSyncWorkOfRoot llamó a renderRootSync, que nuevamente proviene del desarrollo de Ragdoll. Y si sigo bajando así, si sigo simplemente haciendo clic a través de todas estas funciones, recuerda, solo estoy formando una comprensión de alto nivel. No necesito sumergirme realmente en esto. Si miro a través de todas estas funciones, si trato de averiguar de dónde provienen todas estas funciones, vería que todas estas funciones, en realidad provienen del desarrollo de Ragdoll, hasta que llego al siguiente paso cuando las funciones en realidad obtienen un color diferente y provienen de archivos diferentes.

QnA

Analizando React Profiler

Short description:

Analizamos el rastro de rendimiento en el panel de Rendimiento y vemos que la mayor parte del tiempo se dedica a ejecutar el código de desarrollo de React DOM. Cambiamos al panel de React Profiler y grabamos la misma interacción usando React Profiler. El React Profiler muestra los componentes que se actualizan en la aplicación y el tiempo que cada componente tarda en volver a renderizarse. El componente de lista de notas parece ser el más costoso, tardando 10.6 milisegundos en renderizarse por sí solo y 950 milisegundos con sus hijos. Planteamos una pregunta sobre el tiempo perdido en la renderización del componente de lista de notas y discutimos posibles respuestas.

Entonces, esto es bastante fácil de ver haciendo clic en todas las funciones pero es aún más fácil de ver mirando los colores de las funciones y los colores de los rectángulos. Así que los colores de los rectángulos aquí, cuando obtienes algunos objetivos de JavaScript, los colores de los rectángulos no tienen ningún significado concreto. Así que el hecho de que esta función sea anónima, lo siento, así que el hecho de que esta función anónima sea como verde o el hecho de que esta función de flash sink sea como verde, realmente no significa nada, es un color aleatorio pero lo que importa es cuando todas las funciones tienen el mismo color, lo que importa es que todas estas funciones provienen del mismo archivo. Así que lo que puedo ver de inmediato es mientras voy a través de estas funciones, veo que las primeras tres funciones provienen de desarrollos de DOM regulares y lo que esto significa es que todas las siguientes funciones que tienen el mismo color probablemente también provienen del desarrollo de DOM regular.

Muy bien, esto es lo que hemos hecho hasta ahora. Obtenemos un, informe de nuestro usuario, de nuestro gerente de producto sobre una interacción lenta. Hemos producido esta interacción lenta en el panel de rendimiento. Hemos grabado, hemos grabado la interacción con tres picos de actividad de CPU. Nos acercamos a uno de los picos y vimos que el pico es provocado por la persona clave y a su vez llama a un montón de funciones de desarrollo de React DOM. Entonces yo, como desarrollador, no tengo idea de lo que está sucediendo en React DOM. No tengo idea de lo que significan todas estas funciones. Solo veo un montón de código de desarrollo de React DOM y esto se siente súper complicado. ¿Qué diablos está pasando aquí? Pero yo, como desarrollador, yo, como desarrollador, no tengo idea de lo que está sucediendo aquí. Pero en realidad no necesito porque lo que sucede cuando grabo algo y miro a través del rastro de rendimiento y veo que la mayor parte del tiempo en el rastro de rendimiento se dedica a ejecutar algún código de desarrollo de React DOM. En este caso, son 900 milisegundos, 800 milisegundos dedicados a ejecutar algún código de React DOM. Lo que hago es desde el panel de Rendimiento, Lo que hago es desde el panel de Rendimiento, cambio al panel de React Profiler y grabo la misma interacción usando React Profiler. Ahora, el panel de React Profiler no está disponible por defecto. Viene de las herramientas de desarrollo de React. Así que si me estás siguiendo, y si no tienes este panel, esta es la extensión que necesitas instalar. Acabo de soltarlo en el, chat de Zoom. Y si instalas esta extensión, si recargas la página, y si cierras y abres las DevTools, obtendrás el panel de Profiler. Y bueno, intentemos grabar la interacción usando el Profiler. Así que hago clic en grabar, y luego intento escribir en el editor de nuevo. Y de nuevo, ves que la aplicación se vuelve lenta. Y si detengo la grabación, si detengo la grabación en el Profiler, vería lo siguiente. Así que lo primero que el Profiler, el React Profiler me muestra varias cosas, mientras que el panel de rendimiento me está mostrando todo lo que está sucediendo en la aplicación a nivel de funciones concretas. React Profiler me está mostrando todo lo que está sucediendo dentro de React a nivel de componentes. Así que si grabo una interacción usando React Profiler, podría ver todos los componentes que se actualizan en la aplicación. Y entonces lo que veo en este caso es que veo que el Profiler de React me mostró que hubo, cuando escribí en el editor, hubo un re-renderizado que ocurrió. React Profiler llama a eso commit, ese re-renderizado tomó 855 milisegundos con efectos tomando 55 y uno, 56, 57 milisegundos más. Y oops, espera. Esto son spoilers. Esto son spoilers. Déjame volver a grabar esto. Sí, hecho. Así que finge que esto, finge que esto nunca sucedió. Así que me muestra el número de re-renderizados que sucedieron en la aplicación. Me muestra el componente que se renderizó en la aplicación. Y me muestra el tiempo que cada componente tardó en volver a renderizarse. Entonces veamos e intentemos entender lo que está sucediendo aquí. Así que lo primero que veo es que el componente de la aplicación se renderizó. Lo segundo que veo es que el proveedor de modo oscuro se renderizó, luego el proveedor de modo oscuro hizo que el proveedor de contexto se renderizara. El proveedor de contexto hizo que la lista de notas se renderizara. Y luego la lista de notas hizo que el botón de nota se renderizara. Y luego otro botón de nota para renderizar, ¿verdad? Y luego también hubo algún dolor primario tomando nueve milisegundos. Así que los números que tengo aquí, me muestran cuánto tiempo tardó el componente en renderizarse por sí solo, versus con todos sus hijos. Así que puedes ver que los componentes de la aplicación por sí solos tardaron 0.8 milisegundos en renderizarse. Y renderizar aquí significa simplemente llamar a la función del componente, porque eso es literalmente lo que significa renderizar, ¿verdad? Volver a renderizar los componentes de la aplicación literalmente significa llamar a esta función de la aplicación, llamar a los componentes de la aplicación. Los componentes de la aplicación, porque se renderizan, hicieron que el proveedor de modo oscuro se renderizara, hicieron que el proveedor de contexto se renderizara. Eso hizo que la lista de notas se renderizara. Y el componente de lista de notas parece ser el más costoso. Es amarillo. Y tardó 10.6 milisegundos en renderizarse por sí solo, pero él, junto con sus hijos, tardó 950 milisegundos en renderizarse. Y ahora, aquí viene mi primera pregunta para ti. Y esta es una pregunta trampa. Así que si sabes esto, esto es bueno, pero si no lo sabes, me pregunto cuál sería tu hipótesis sobre esto. Así que aquí está mi primera pregunta que te hago. Entonces estoy mirando a través del Rect Profiler, y veo que el componente de lista de notas, parece ser el más costoso, tardó 10 milisegundos en renderizarse por sí solo, o casi un segundo para renderizar con todos sus hijos. Pero si miro a los hijos del componente de lista de notas, solo vería dos hijos. Vería un botón de nota que tarda 15 milisegundos en renderizarse y otro botón de nota que tarda seis milisegundos en renderizarse, lo que suma 20.

Bug y Solución Alternativa del React Profiler

Short description:

Se descubre que el Profiler rastreado tiene un error en el que no renderiza todos los componentos cuando hay demasiados en el profiler. Al alejar la imagen o ampliar la pantalla de DevTools, se pueden renderizar más componentes. El React Profiler no maneja esto bien, a diferencia del Panel de Chrome DevTools. La solución alternativa es acercar la imagen o renderizar menos componentes. Al reducir el número de botones de nodo de 700 a 100, el rendimiento mejora significativamente.

Tian pregunta, ¿fue la reconciliación? También es una buena suposición, no, la reconciliación en realidad no es visible en el archivo Recto en absoluto. Es la causa que el archivo Recto realmente no te muestra. Oh sí. Entonces Gregers, lo siento, Gregers, ese es probablemente el nombre correcto, lo siento, ¿es así como se pronuncia? Sí, casi perfecto. Sí, está bien. Lo siento por cualquier imperfección. Entonces Gregers dice que en su profiler, hay más hijos en Recto y, sí, sí, sí, Gregers también, sí. Entonces lo que está sucediendo aquí, y la razón por la que estoy mostrando esto, es porque si te encuentras con esto por primera vez, esto es tan desconcertante, esto es tan confuso. Lo que está sucediendo es que las DevTools rastreadas tienen un error, o tal vez es una decisión de design, no lo sé. Pero las DevTools rastreadas, el Profiler rastreado tiene un error, que es cuando tienes demasiados componentes en el profiler, lo que sucede cuando el Profiler rastreado no puede ajustar todos estos componentes en la pantalla, simplemente no los renderiza. Y esto es muy molesto porque es muy confuso cuando estás trabajando con el Profiler rastreado por primera vez. Podría desorientarte totalmente, definitivamente me desorientó la primera vez que vi esto. Pero si alejas la imagen, si haces la pantalla de DevTools más ancha, verías como el Profiler rastreado obtiene cada vez más espacio para renderizar el componente que necesita. Estos componentes, aparecen, como, más componentes en realidad. Así que aquí podrías ver, pasaría el ratón por la lista de notas, y puedes ver que tengo, como, muchos más componentes de botón de nodo, cada uno de ellos tomando uno, dos, tres, quizás cinco milisegundos. Así que esto es algo muy molesto. Creo que es design, es una decisión de design. No me gusta la decisión de design, pero esto es algo. Si alguna vez ves un espacio en blanco en el React Profiler en medio de la grabación, lo que esto significa no es que el profiler rastreado se fue y pasó algún tiempo haciendo... No sé, simplemente fue, no significa que React estaba inactivo o React estaba haciendo algún otro trabajo. Eso simplemente significa que el React Profiler no pudo ajustar todos los componentes en el espacio. El Panel de DevTools de Chrome maneja esto bien, el React Profiler, desafortunadamente, no. Muy bien, hemos resuelto el truco. Gran trabajo, a todos. Hemos resuelto el rompecabezas y hemos aprendido que la lista de nodos tarda 950 milisegundos en renderizarse. Simplemente porque renderiza un montón absoluto de botones de nodo. Solo mira esto. Botón de nodo, botón de nodo, botón de nodo, botón de nodo. Y si paso el ratón por cualquiera de estos botones de nodo, podría ver a qué componente corresponde realmente. Así que podría ver que cada uno de estos botones de nodo es solo un elemento en esta lista. Así que en este punto ya podrías tener algunas ideas sobre cómo resolver esto. Pero cuando estoy depurando cosas, lo que siempre trato de hacer antes de averiguar realmente la solución, lo que trato de hacer es tratar de llegar al final e intentar averiguar por qué exactamente está ocurriendo este cuello de botella de performance. Porque a veces cuando hago eso, encuentro una solución que es mucho más simple y fácil que cualquier solución, cualquier solución intermedia que pueda imaginar. Entonces digo esto, ¿alguien pensó en la virtualización? ¿Podrías enviar un más, si pensaste en la virtualización cuando estaba mostrando esta enorme pantalla, enorme lista de nodos. Oh sí. Entonces algunas personas pensaron en la virtualización, ¿verdad? Y esa es una optimization que podrías aplicar aquí, pero aún no vamos a hacer eso. Así que sí, la pregunta de la solución alternativa en el chat. ¿Cuál es la solución alternativa para esto? Sí, la solución alternativa para esto es simplemente acercar la imagen, o si tienes una buena idea de qué está causando que se rendericen tantos componentes, intenta renderizar menos de ellos. Entonces en este caso, estoy renderizando 700 botones de nodo. Déjame desactivar las estadísticas de renderizado de marcos. Estoy renderizando alrededor de 700 botones de nodo. Entonces, si renderizo solo cien botones de nodo, entonces el Filer de Tractor tendría una mejor oportunidad de ajustar todos ellos. Entonces voy a hacer justo eso. Hagamos eso. Entonces voy a limpiar la grabación y eliminar todos los botones de nodo y crear cien nodos y volver a grabar la misma interacción, pero esta vez solo para cien nodos. Y sí, ves que el problema se ha ido. Puedo ver todos los botones de nodo y puedo ver que la interacción ahora es mucho más rápida. Toma solo 145 milisegundos. Todavía es lento. Cien milisegundos todavía son lentos, pero, bueno, ahora obtiene todos los componentes.

Análisis de Re-renderizados de Componentes

Short description:

Después de analizar el profiler, descubrimos que la aplicación es lenta debido a las actualizaciones de componentes en el componente de la lista de notas. Investigamos por qué se renderizan estos componentes y encontramos que el hook useState y ciertas funciones estaban causando los re-renderizados. Para optimizar esto, utilizamos el hook useCallback para memorizar las funciones. Sin embargo, a pesar de nuestros esfuerzos, la prop nodes aún necesita cambiar, lo que dificulta la optimización adicional. Como resultado, necesitamos explorar optimizaciones en los componentes renderizados por el componente NodeList.

Muy bien, esto es lo que he aprendido hasta ahora. Después de revisar el panel de performance y después de darme cuenta de que todo el código aquí proviene de React, cambio al profiler y hago clic en grabar y grabo el perfil, la interacción, y me doy cuenta de que la aplicación es lenta porque tenemos un montón de, tienen actualizaciones de componentes, las actualizaciones del componente de la lista de notas, y el componente de la lista de notas hace que se rendericen muchos botones.

Ahora, aquí está la siguiente pregunta. ¿Por qué exactamente está sucediendo esto? ¿Por qué se re-renderizan todos los botones de las notas? Y para responder a esta pregunta, esto es lo que voy a hacer. Así que hay varias formas de responder a esta pregunta. Vamos a ver todas estas formas, todas las formas a lo largo de toda la masterclass. Pero lo primero, lo más simple que siempre hago es ir a la configuración del profiler. Hago clic en la configuración aquí. Voy a la configuración del profiler y me aseguro de que el checkbox de grabar por qué se renderizó el componente mientras se perfila está habilitado. Y si la lista de verificación está habilitada, y si vuelvo a grabar la interacción, y miro lo que está sucediendo en el profiler ahora, vería que cada componente en el que pasaría el cursor tendría esta sección que dice ¿por qué se renderizó esto? Así que veamos por qué exactamente se renderizan todos estos componentes.

Así que los componentes de la aplicación se renderizan porque su hook número uno cambió. Veamos cuál era el hook número uno. Así que voy a ir a ARP.slashindex.js6. Y miraré mis hooks y veré que mi hook número uno era el hook useState. Parece un hook que contiene todas las notas como, estoy ignorando todo el código que está allí abajo. ¿Verdad? No me importa. Solo miro el primer hook y el primer hook es el hook que tiene todas las notas. Y bueno, cuando estoy escribiendo en el editor de notas las notas obviamente se actualizan. Así que supongo que este es un re-renderizado útil. Realmente no podemos hacer nada con él. Luego sigo bajando, veo que el proveedor de modo oscuro se renderiza porque sus hijos cambiaron y la sonda de hijos siempre cambia cada vez, así que tampoco puedo hacer mucho con ella. El proveedor de contexto simplemente nunca muestra por qué se redimió. Simplemente se renderiza cada vez que lo re-renderizas. Luego los componentes de la lista de notas, el componente de la lista de notas cambió porque su prop de notas cambió. Y también porque su prop de on new notes requested a know on delete all requested props cambió. Así que Emmett hace una gran pregunta. ¿Es posible obtener el nombre del hook en lugar de un número porque es un poco confuso? Desafortunadamente, no. Así que hablaremos de esto en la segunda parte de la masterclass. React DevTools no puede, React provider no puede darte los nombres de los hooks, así que necesitas hacer un poco de salto extra de ida y vuelta para averiguar realmente qué es el hook. Y hay trampas. Así que justo ahora fui y vi que el hook número uno cambió y era este hook, pero realmente no puedes hacer eso en la mayoría de los casos. Mostraré la aplicación del mundo real donde esto no funciona. Y veríamos cómo hacer coincidir los números de los hooks con los hooks reales. Pero hablaremos de esto un poco más tarde. Así que el componente NodeList, el componente NodeList, el componente NodeList se renderizó porque sus nodos en su nodesRequested a nodedeleteAllRequested, los hooks cambiaron. Así que esto parece más interesante. El on your nodes requested a nodedeleteAllRequested parece funciones, ¿verdad? Y sucede muy a menudo que algunas funciones que tenemos día, si no están memorizadas, simplemente causarían que se renderice algún componente. Así que vamos, vamos a echar un vistazo a la NodeList y veamos si hay algo que podamos optimizar con ella. Así que NodeList, voy a ir a la NodeList, aquí están todas mis prompts que tengo nodos y aquí están todas las nuevas nodes requested a ondeleteAllRequested. Y si voy a, si comento clic en la NodeList, podría ver dónde exactamente se llama a la NodeList. Y veamos, on newNodesRequested crea nuevos nodos y ondeleteAllRequested deleteAllNodes y si hago clic en estas props, si veo qué valores obtienen estas props, vería que efectivamente, cada vez que se renderiza el componente de la aplicación, recreamos la función saveNodes, recreamos la función createNewNodes, recreamos la función deleteAllNodes y todas estas nuevas funciones, incluso si nada cambia dentro de ellas, se pasan a la lista de notas y hacen que la lista de notas se renderice. Entonces, ¿cómo resolvemos esto? Dime, ¿cómo resolvemos esto? ¿Qué hacemos con estas funciones? ¿Para evitar que cambien cada vez? Sí, le damos un use callback. Sí, los envolvemos con un use callback. Así que está bien, todo el molesto arrastre de la caldera, hagamos esto. Así que createNewNodes, voy a envolver createNewNodes con use callback. Use callback, yada, yada, yada, cuerpo de la función, array de dependencias. Necesito importar el use callback de React, o necesito que se importe, y necesito escribir el array de dependencias, y React Profile, oh, lo siento, no React Profiler, GitHub Copilot es en realidad a veces bueno en los arrays de dependencias. Pero si no es así, si no es así, veamos, veamos, ¿qué tenemos aquí? Tenemos la función getNodes que se importa. Tenemos la función setNodes, que proviene del useState, pero no necesitamos pasar esta función al array de dependencias, porque React garantiza que esta función es la misma cada vez. Así que no va a cambiar. ¿Y qué más tenemos aquí? SetActiveNodeId, eso también es el hook setState. Y Node.Txt, ¿de dónde viene Node.Txt? Oh, no, es solo grados, yada, yada, yada, Map. PutNodes, eso también, bueno, parece que no tiene dependencias, ¿verdad? Porque sabes, es getNodes, setNodes, parece que no tiene dependencias. Así que simplemente voy a poner ninguna dependencia en él. Y ahora delete all nodes. Veamos, use callback, yada, yada, yada. Delete nodes, es alguna función externa, se importa getNodes, setNodes, setActiveNodeId, así que esto también no tiene dependencias. Muy bien, mira, hemos memorizado nuestras funciones. Así que veamos qué ha hecho esto a nuestra aplicación. Así que voy a recargar, y voy a hacer clic en Grabar, y voy a presionar el mismo botón del teclado de nuevo. Y veamos que el componente NodeList todavía se re-renderizó, y los dos componentes, las dos funciones que hemos memorizado con estos callbacks, ya no cambian, pero la prop nodes todavía cambia, y la prop nodes todavía tiene que cambiar porque contiene todos los nodos existentes. Cuando estoy escribiendo en los nodos, la prop nodes que contiene todas las prop existentes, tiene que cambiar. No hay forma de prevenir este cambio. Así que, bueno, acabamos de hacer un montón de trabajo para nada. Felicidades. No podemos optimizar. Lo que esto significa es que no podemos optimizar el componente NodeList, así que tenemos que seguir adelante. Así que veamos. El componente NodeList renderiza un montón de otros componentes.

Optimizando el Componente de Entrada de Filtro

Short description:

Podemos optimizar el componente de entrada de filtro utilizando memo. Al agregar memo al componente, podemos evitar que se renderice cuando se renderiza su componente padre.

Tenemos el componente de entrada de filtro que se vuelve a renderizar porque se renderizó su componente padre. Así que ninguna prop cambió, ningún estado cambió, ningún hook cambió. Es solo que se renderizó el componente padre. ¿Alguna idea de cómo resolvemos esto? ¿Cómo evitamos que el componente se renderice cuando se renderiza su componente padre? Sí. Es memo. Entonces, vamos al componente y vamos a ponerle un memo. Entonces es filtro, ¿qué era? Entrada de filtro. Índice de entrada de filtro de JSX. Entonces, sí, plantilla básica de React, ups, no. No necesito medios, lo que sea que fuera. Importar memo de React, recargar, grabar, detener la grabación. Muy bien, mira esto. Ahora hemos optimizado nuestro componente de entrada de filtro y el componente de entrada de filtro ahora es gris, no se renderizó, buen trabajo yo.

Optimizando los Componentes del Botón Nodo

Short description:

El componente de la lista de nodos renderiza muchos componentes de botón de nodo, causando problemas de rendimiento. Exploramos diferentes soluciones para prevenir re-renderizados innecesarios, como usar useCallback o la propagación de eventos. Pasamos las funciones necesarias como props al componente del botón nodo y lo envolvemos con memo para optimizar el rendimiento. Al implementar estos cambios, mejoramos significativamente la velocidad de la aplicación y demostramos la importancia de perfilar y optimizar el rendimiento.

Muy bien, pero eso nos deja con el mayor cuello de botella. La parte más costosa del componente de la lista de nodos la parte más costosa de los componentes de la lista de nodos, como el 99% de todos sus hijos son todos los componentes del botón nodo que la lista de nodos renderiza. Y si paso el cursor sobre todos estos botones de nodo, vería que cada componente se renderiza porque su prop en nodo activado cambió. Eso de nuevo parece algo a lo que podrías aplicar useCallback, ¿verdad? Quizás, quizás no lo sé. Quizás la función cambia para bien.

Bueno, tenemos el componente del botón nodo y cada uno de los componentes del botón nodo tarda solo un milisegundo en renderizarse pero porque tienen muchos de ellos juntos, tardan mucho. Así que veamos si podemos prevenir que el componente del botón nodo se vuelva a renderizar. Veamos, así que tenemos el botón nodo, en realidad, ahora, veamos, busquemos de una manera diferente. Una forma de encontrar esto es ir al código y encontrar como el índice del botón nodo a J seis o lo que sea. Pero si ese componente se usa en varios lugares de la aplicación, entonces podría ser muy difícil de encontrar qué lugar realmente renderiza este componente. ¿De dónde viene este renderizado? Así que una cosa que me gusta hacer para encontrar dónde vive este componente en el código es hacer clic en este componente y luego cambio al panel de componentes y este componente permanece enfocado, ¿verdad? Y miro el panel de origen que me muestra el lugar exacto donde se renderizó ese componente. Así que ahora si copio esto, y si voy a la lista de notas índice solo seis 35, bueno, no es el lugar exacto, supongo que los mapas de origen están un poco desviados pero aquí en la línea 37, este es el componente exacto que el botón de notas que estamos renderizando. Y aquí está su propiedad onThatActivated. Mira, es una función anónima de nuevo, pero es una función anónima en un bucle. Así que normalmente cuando tenemos una función anónima, lo que haríamos es tomar esa función anónima y la envolveríamos con useCallback. Aquí, no podemos hacer eso porque no podemos usar hooks en un bucle. Eso rompería las reglas de los hooks. Los hooks no pueden ser usados condicionalmente. Así que mi próxima pregunta para ti es ¿alguna idea de cómo podríamos resolver esto en lugar de usar useCallback? Veamos cómo funciona este onNotActivated. Para transferir esto, para hacerlo más fácil de transferir, veamos cómo se usa la propiedad onNotActivated. Voy a, ¿puedo abrir esto por separado? Oh sí, aquí lo abro en una vista dividida separada. Y aquí está el componente del botón nodo. Recibe la prop onNotActivated y simplemente la pasa a onClick. Y aquí creamos la función onNotActivated y se llama a alguna función padre que también se llama onNotActivated y le pasa un ID. ¿Alguna idea de cómo podríamos resolver esto? ¿Cómo podríamos prevenir que la prop onNotActivated cambie? ¿No? Svetlana sugiere que podemos crear una función de manejo en el nivel superior como const que ejecuta onNotActivated. Richard sugiere referencia estática y tomemos el ID dentro de los componentes. Así que no sigo completamente la primera idea, lo siento. La segunda idea, sí, esta es una de las soluciones. Y quizás Svetlana, quizás también quisiste decir lo mismo. Pero sí, aquí hay una forma de resolver esto. Así que en lugar de pasar la función anónima que estoy creando cada vez, ooh, Jaggers también sugiere la propagación de eventos y eso es realmente un truco genial. Podrías poner, podrías poner el, podrías poner un oyente de eventos en algún lugar más alto, por ejemplo, en este diff. Y en lugar de manejar el clic en cada uno de estos nodos, manejarías un clic en el nivel de esta lista de nodos. Y entonces el evento de clic se propagaría. Pero sí, eso plantea su propio desafío. Es difícil averiguar qué botón de nodo corresponde a qué ID, ¿verdad? Así que eso es una buena solución alternativa, pero definitivamente tenemos las soluciones más fáciles aquí. Así que Svetlana, lo que estás sugiriendo para entender, para entender tu solución, lo que estás sugiriendo es hacer algo como esto, ¿verdad? Const handle active node equals on.activated ID y luego pasar esto aquí. ¿Es esto correcto? Oh no, no, después de que afirmas. Muy bien, pero aquí está el desafío. ¿Cómo obtienes el ID? Porque el ID solo está disponible dentro del mapa, ¿verdad? Así que si hacemos esto, no tendríamos ningún acceso al ID. Ese es el desafío para esto, sí. Si esto no necesitara ningún acceso al ID, podríamos simplemente moverlo todo hacia arriba y envolverlo con este callback y esa sería una gran solución, pero ahora que podemos hacer esto, sí, lo que Emad está sugiriendo, Emad, lo siento, quizás lo pronuncié mal, lo que Emad está sugiriendo, lo que Richard está sugiriendo es que podemos simplemente pasar esta función por sí misma y llamarla desde dentro del componente. Así que hagamos justo eso. En lugar de llamar a la función, en lugar de crear la función en el nivel de la lista de nodos y luego pasarla al botón nodo, voy a pasar las funciones onNotActivated e ID. Lo siento, onNotActivated, y props ID y aquí dentro del botón nodo, voy a recibir la nueva prop ID y voy a recibir la prop existente onNotActivated y voy a llamar a onNotActivated ID justo aquí. Y una última cosa que voy a hacer es que voy a poner un memo alrededor del botón nodo porque incluso si no cambian las props, el componente seguirá re-renderizándose por defecto. Así que para prevenirlo de cambiar, para prevenir que se vuelva a renderizar, necesito envolverlo con memo. Muy bien, ooh, tenemos algún error. Veamos cómo funciona esto. Así que cambio al panel del profiler y mantengo el nodo demasiado temprano. Abro el nodo, intento escribir en el nodo y no lo está grabando. ¡Mira esto! Mira lo bueno que es esto. Evitamos que todos los botones de nodo se renderizaran. Eso es increíble. Hemos resuelto el primer problema de performance. Mira, si habilito las estadísticas de renderización de cuadros ahora y si intento escribir en el editor, los trozos rojos, incluso con un estrangulamiento de CPU de 4x son mucho, mucho más pequeños de lo que eran antes. Pero si comando esta solución o simplemente la escondo bajo la solución, ¿verdad? Y, oh, acabo de detener el servidor de pies. Eso no es bueno. Y ahora intento escribir. Mira lo lento que es esto. Es terriblemente lento. Y si vuelvo a aplicar la solución entonces la aplicación se vuelve mucho, mucho, mucho más rápida. Todavía no es 60 FPS y todavía hay más cosas para optimizar. Pero el objetivo de esta masterclass no es mostrarte la optimization, el objetivo de esta masterclass es mostrarte los enfoques para perfilarlo. Y esta es mi primera forma de perfilar cualquier problema de performance, cualquier problema de performance que encuentro. Lo grabo para la traza de performance. Y si veo que la mayoría de estas cosas están sucediendo en direct, cambio al profiler direct y lo grabo para el profiler direct y habilito grabar qué componentes se renderizaron mientras se perfilaba. Y luego miro todos los componentes, encuentro los componentes más costosos e intento prevenir que se vuelvan a renderizar de cualquier manera que pueda pensar. Y si hago esto, mi aplicación se vuelve mucho más rápida.

Masterclass de Depuración de Rendimiento de React Preguntas y Respuestas

Short description:

La memorización no es gratuita, pero en la mayoría de los casos, el costo de volver a renderizar cada componente es mayor que el costo de memorizar los componentes. Es mejor memorizar solo los componentes que realmente lo necesitan. El perfilador de React muestra los componentes que no se renderizaron con un ancho aproximado basado en renderizados anteriores. Aprendimos a usar Chrome DevTools y React Profiler para depurar problemas de rendimiento. También tenemos disponible un diagrama de flujo de rendimiento de React. En la siguiente parte, cambiaremos a la aplicación Widgets Editor y abordaremos el rendimiento pesado de la aplicación y el modo React Street. Si React Profiler se atasca, intente desactivar el estrangulamiento de la CPU o grabar interacciones más cortas. El modo React Street no obliga a renderizar los componentes dos veces en el panel del perfilador.

Entonces, esto concluye la primera parte de la masterclass. Permítanme responder a sus preguntas y luego tomarán un descanso. Entonces Emmett pregunta, ¿no será esto costoso si estás memorizando muchas cosas? En general, no lo sería. La memorización no es gratuita, ¿verdad? La memorización no es gratuita. Tiene los códigos de la CPU porque todavía tienes que comparar todos los parámetros que pasas a use memo o React tiene que comparar todos los parámetros que pasas a use memo. Tiene los costos de memoria y de hecho si estás asistiendo a React Berlin en React Berlin habrá una charla sobre los costos de memoria de use memo. Estoy muy emocionado por ello. Estoy realmente curioso por aprenderlo. Pero en general, el costo en la mayoría de los casos el costo de volver a renderizar cada componente en la mayoría de los casos, es mayor que el costo de memorizar los componentes. Y me preguntan de vez en cuando, ¿deberías usar memo en todo? Y mi respuesta a esto, si puedes entender qué es exactamente lo que necesitas usar memo, si puedes usar el pintado del perfilador de React, si puedes usar las herramientas de desarrollo de Chrome, entonces no necesitas usar memo en todo. Porque en cualquier momento si tu aplicación es lenta, podrías simplemente grabar la traza, ir al perfilador de React, encontrar el componente más costoso y memorizarlo solo a él. Y esa sería la mejor solución. Solo memorizarías las cosas que realmente necesitan ser memorizadas. Pero si no puedes usar el perfilador de React, si no puedes usar el pintado de rendimiento de Chromium, entonces si te sientes poco familiarizado con ellos, entonces o si tus, ya sabes, compañeros de equipo se sienten poco familiarizados con ellos, entonces sí, probablemente envolver todo con memo y use memo y use callback es la mejor solución hasta que salga el olvido de React. Quimqui pregunta, ¿por qué está en gris? ¿Por qué esto está en gris, pero esos componentes todavía toman un ancho en el gráfico de llamas? Así es como funciona el perfilador de React. Memoriza el tiempo que cada uno de los componentes tardó en renderizar, creo que durante su primer renderizado o algo así, y luego simplemente usa ese ancho aproximado cuando el componente no se renderiza. Así que esta es la diferencia entre el panel del perfilador y el panel de rendimiento de Chrome. En el panel de rendimiento, si algo no sucede en el panel de rendimiento, React simplemente no lo mostrará. En el panel del perfilador si algún componente no se renderiza, React aún lo mostrará con algún ancho, pero con algún ancho que intentaría inferir de los renderizados anteriores, pero te mostraría explícitamente que este componente no se renderizó. Muy bien, esa fue la primera parte de nuestra masterclass. Aprendimos a usar las herramientas de desarrollo de Chrome, aprendimos a usar el perfilador de React para depurar problemas de rendimiento, para ver qué componentes se renderizan, por qué exactamente se renderizan, etc. Y todo esto, todo este proceso por el que pasaron, viene de mi cabeza. Como grabar cosas en las herramientas de desarrollo de Chrome, luego cambiar al perfilador de Direct si es principalmente React, etc., etc. Todo esto viene de mi cabeza. Pero para todos ustedes, y es posible que ya hayan visto esto porque hay un enlace en el documento de Google. Para todos ustedes, he preparado este diagrama de flujo de rendimiento de React que pueden encontrar en los datos compartidos del documento de Google, o pueden encontrarlo en este enlace del diagrama de flujo de rendimiento de React. Permítanme copiar el enlace y enviarlo. No puedo copiar ese enlace. Permítanme escribir ese enlace en el chat. Oh no, permítanme abrir ese enlace. Y ahora puedo copiar ese enlace y pegarlo en el chat. Um... Y, bueno, esto es más o menos mi proceso de depuración de interacciones lentas de React. Lo que hemos hecho sería ahora a través de la primera parte de la interacción, a través de la primera parte del trabajo, grabamos la interacción usando las herramientas de desarrollo con un estrangulamiento de CPU de 4x y nos dimos cuenta de que lo que está sucediendo en la interacción es principalmente código de React. Y luego fuimos y comprobamos qué está sucediendo. Bueno, en realidad no comprobamos el root sync aleatorio y lo haremos en la primera, te mostraré por qué es importante en la tercera parte de la masterclass, pero nos dimos cuenta de que lo que está sucediendo en la aplicación es principalmente el renderizado de React. Así que, abrí el perfilador de React y grabé la traza dentro usando el perfilador de React, e intenté encontrar los componentes más costosos, los componentes que se renderizan con más frecuencia y que toman más tiempo. Eran los botones de nodo. Eran todos los botones de nodo. Y luego usé ReactiveTools, configuraciones, grabar por componente renderizado para responder por qué exactamente se renderizaron estos componentes. Sí, y luego encontré cómo renderizarlos menos a menudo. Así que, esta fue solo una parte del diagrama de flujo que usamos. Veamos cómo se aplica esta parte no a aplicaciones simplistas, como la aplicación que acabamos de ver, sino a aplicaciones reales, grandes y enormes con muchos componentes, muchas cosas en ellas, y para responder a eso, cambiemos a la segunda aplicación que tenemos en el repositorio, que se llama Widgets Editor. Así que vamos a cd Widgets Editor, voy a instalar las dependencias, voy a ejecutar yarn start aquí también. KoenGui pregunta, ¿qué hago si mi aplicación es tan pesada que RactorFiler se atasca procesando data? Bueno, no tengo una buena respuesta para esto. Es una situación triste en la que estar. Es desafortunado. Así que lo primero que hacemos es si tienes habilitado el estrangulamiento de la CPU, entonces tal vez desactivarlo podría ayudar. No estoy seguro si el estrangulamiento de la CPU solo estrangula la página o también las extensiones, realmente no estoy seguro de eso. Así que tal vez desactivarlo podría ayudar. La segunda cosa que ayuda es simplemente grabar más corto. Así que, no empezar la grabación cuando se abre la aplicación, sino hacer la grabación de solo la interacción lenta, solo el bit que es lento. Y de lo contrario, si ninguna de estas cosas ayuda, realmente no sé qué hacer.

Analizando el Rendimiento de una Aplicación Real

Short description:

Vamos a explorar una aplicación real con problemas de rendimiento. Cambiar la propiedad del tipo de datos hace que la aplicación se congele y desencadena re-renderizados innecesarios. Hay herramientas disponibles para probar automáticamente las interacciones y medir el rendimiento de React. El autor proporciona un artículo sobre el monitoreo del rendimiento de React. Utilizando el panel de rendimiento y el perfilador de Rect, podemos analizar el rendimiento de la aplicación e identificar áreas de mejora.

Pero no lo recuerdo y eso es fácilmente googleable. Así que echemos un vistazo a una aplicación real compleja. Esta es una aplicación, es una aplicación de código abierto que un cliente mío amablemente me permitió usar para una masterclass. Es una versión artificialmente ralentizada de la aplicación. Y aquí hay un problema de performance que tiene esta aplicación. Así que voy a habilitar la ralentización de la CPU 4x y voy a habilitar la renderización, el inicio de la renderización de los marcos de nuevo. Veamos aquí un problema de performance, así que si abro el... Espera, necesito explicar lo que hace esta aplicación. Así que la aplicación que tenemos aquí es solo una aplicación básica de widgets. Es como un seguimiento de código bajo, que es genial, puedo soltar algunas aplicaciones en el lienzo, lo siento, puedo soltar algunos widgets en el lienzo, puedo establecer propiedades para estos widgets. Puedo conectar estos widgets entre sí con alguna lógica. Podría moverlos, etc., etc. Como puedes ver, tengo algunos widgets filtrados y luego, algunas tablas y cosas así. Así que esta aplicación tiene un problema de performance, que es si abro cualquier panel de propiedades y si intento, como por ejemplo, este panel de propiedades de filtro por contenido, panel de propiedades del campo de búsqueda, y si intento cambiar el tipo de data, del tipo de data que tengo ahora, oh espera, no habilité el estrangulamiento de la CPU, del tipo de data que tengo ahora a este mismo tipo de data que tengo, así que básicamente, de texto a texto, nada debería cambiar en la aplicación, ¿verdad? Nada debería, como no estoy cambiando nada, pero si hago eso, si cambio la propiedad del tipo de data de texto a texto, lo que sucedería es que mi aplicación se congelará durante un buen rato. Podrías ver esto aquí, obtengo un montón de rojo y también un montón de amarillo. Así que hago clic en texto, selecciono texto, y mi aplicación se congela. Este es un problema de performance, no debería pasar nada en la aplicación cuando cambio la propiedad de texto. Y también hay otra forma de ver este problema de performance. Así que si vas a los componentes de rec y vuelves a configuraciones, lo siento, al perfilador de rec y vuelves a configuraciones, cambias al panel general y haces clic en resaltar actualizaciones cuando los componentes se renderizan, lo que obtendrías es que cada vez que cualquier componente se renderiza, verías ese componente resaltado. Así que por ejemplo, si estoy escribiendo aquí, oof, puedes ver todo renderizándose mientras estoy escribiendo. Esto es realmente lento, esto realmente no debería suceder, pero está sucediendo, ¿verdad? Y lo mismo también sucede si selecciono texto y luego hago clic en texto. Así que nada, no cambio nada en la aplicación, pero toda la aplicación se vuelve a renderizar. Esto es realmente lento y realmente ineficiente. Así que intentemos averiguar de dónde vienen todos estos renderizados e intentemos averiguar qué es lo que hace que la aplicación sea lenta y cómo podemos hacerla más rápida. Alexandra pregunta, ¿existe alguna herramienta para probar automáticamente un montón de interacciones para detectar posibles problemas de performance? Sí y no. Así que, debugger, INF tester. No, render. Zhu-zhu-zhu-zhu. INF. Creo que debugger, sí. Oh no, es, sí, INF debugger. Así que, hay una herramienta que es muy buena, nunca la he usado, pero conozco al desarrollador, sé que el desarrollador realmente se preocupa por la performance y el equipo tiene una gran experiencia en performance. Esta herramienta, podrías poner cualquier sitio web en ella. No sé, reddit.com, pongamos Reddit, es lento, ¿verdad? Voy a poner una nueva herramienta allí, y ejecutará una prueba e intentará hacer clic básicamente en todo, okay, no, no voy a hacer eso, intentará hacer clic básicamente en todo en la pantalla y grabará cuánto tarda cada clic. Y eso es bastante conveniente. No te dice exactamente qué está pasando durante ese clic, pero aún así es conveniente ver qué es lento. Luego, otra cosa que podrías hacer para averiguar realmente, como cuándo está sucediendo eso. Otra cosa que podrías hacer para medir las interacciones, medir partes de la aplicación, averiguar qué las hace lentas, es configurar algunas tooling para recoger los data de performance de React para ti. Y tengo un artículo sobre esto. Así que si vas a 3perf.com, que es mi sitio web de consultoría, y vas a artículos y guías, y buscas aquí cómo monitorear la performance de React, encontrarás este artículo, que voy a enviar al... En realidad, lo siento, voy a enviar ambos enlaces al chat. Encontrarás este artículo que habla sobre cómo medir la performance de React en el código. Así que cómo instrumentar cada interacción, cómo recoger los data, y enviarlos a las analíticas, y qué más hacer con ellos. Es mi conocimiento más actualizado en cómo medir la performance de React en la naturaleza. Así que con eso en mente, vamos a sumergirnos en nuestra interacción lenta. Así que tenemos una interacción lenta, hago clic en texto, y todo se renderiza. Así que lo primero que siempre voy a hacer es cambiar al panel de performance e intentar grabar lo que está sucediendo en la aplicación usando el panel de performance. Así que habilito el estrangulamiento de la CPU, hago clic en grabar, elijo texto, y detengo la grabación. Déjame cerrar esto. Y en la grabación, de nuevo, veo un montón de cosas. Veo un gran pico de gris al principio de la grabación, que parece ser solo la sobrecarga de la creación de perfiles. Así que no es algo de lo que necesite preocuparme. Veo otro gran pico de JavaScript en medio de la grabación, y luego un pico más pequeño de JavaScript al final de la grabación. Y si paso el ratón por encima, si miro lo que está pasando, veré que... Sí, el primer pico de JavaScript parece suceder justo cuando hago clic en el valor de texto en el desplegable. Podrías ver en los marcos que comienza cuando el desplegable está abierto, y luego a medida que avanza, la pantalla se actualiza, y obtengo todos estos re-renderizados que me mostró el perfilador de direct, sucediendo, sucediendo, sucediendo, sucediendo. Y luego obtengo otro pico de actividad de JavaScript, que también aparentemente re-renderizó algunos componentes, pero este fue más pequeño, este fue más barato. Así que hay muchas cosas sucediendo ahora aquí. Es un gran ferrocarril, así que vamos a acercarnos al primero, al primer pico, y vamos a intentar ver qué está pasando aquí

Analizando las Renderizaciones del Profiler de React

Short description:

Abro el panel de propiedades, desactivo los destellos verdes y comienzo a grabar la interacción. El Profiler de React muestra 13 rerenderizaciones, algunas más costosas que otras. Analizo cada renderización y anoto los componentes involucrados. La primera renderización tarda 50ms, renderizando el encabezado del editor y el editor de widgets. Tomo notas usando el diagrama de flujo como guía. Identifico la función prevalente rendererRootSync y cambio al Profiler de React para encontrar los componentos más costosos. Continúo analizando cada renderización y anotando los componentes involucrados.

Voy a abrir el panel de propiedades de nuevo. Voy a desactivar estos destellos verdes porque son un poco molestos, de acuerdo. Y abro el, no, por favor abre. No seas buggy. Sí. Abro el panel de propiedades de nuevo y abro el desplegable. Y ahora comienzo a grabar, selecciono texto, detengo la grabación, y aquí está lo que veo. ¿Detuve la grabación? Espera. Esperemos un poco. Esperemos un poco. No detengamos la grabación inmediatamente porque recuerda que hubo un período de inactividad y luego otro pico de CPU. Así que simplemente miremos todos ellos juntos. Así que voy a abrir, hago clic en grabar, selecciono texto, espero un poco, y luego detengo la grabación. ¡Yay, hemos terminado! Así que veamos lo que nos muestra el archivo de rector.

Lo primero que veo es que tenemos no uno esta vez, sino 13 rerenderizaciones que ocurrieron en la aplicación. Algunas de estas renderizaciones fueron más costosas. Algunas de estas renderizaciones fueron menos costosas. Las renderizaciones más baratas, son cortas en altura, las renderizaciones más costosas, son altas en altura. Esa es una forma bastante fácil de encontrar las renderizaciones más costosas. Y si paso por cada una de ellas, vería todos los componentes que se rerenderizaron durante cada una de estas renderizaciones. Así que veamos qué está pasando. Pasemos por cada una de estas renderizaciones e intentemos averiguar qué está pasando en cada una de estas renderizaciones, ¿verdad? Así que veamos, la primera renderización, la costosa, toma 50 milisegundos y renderiza dos componentes separados. El encabezado del editor, que toma 10 milisegundos y renderiza el editor de widgets, que toma 47 milisegundos. Esto no suma, ¿verdad? 47, nueve, aún 47. Esto es algo que veo a veces en las herramientas de directiva, solo números. No suficientes números entre componentes y números en la, como duración total de renderización. No sé de dónde viene esto. Probablemente sea otro bug de las herramientas de directiva. Pero veo que mi componente de encabezado del editor se renderizó y veo que mi componente de editor de widgets se renderizó. Veamos el siguiente. Y este es en realidad el momento en el que normalmente voy y empiezo a tomar notas, porque hay muchas cosas sucediendo y es útil tomar notas. Y si revisas el diagrama de flujo que tenemos aquí, verías las notas sugeridas aquí mismo en el diagrama de flujo. Así que aquí está lo que hemos hecho hasta ahora. Grabamos la interacción, usamos las DevTools, miramos qué está pasando allí, notamos que es principalmente código de React. Me salté un paso, pero busqué, si lo estaba haciendo completamente de la manera en que siempre lo hago, es que buscaría qué función es prevalente entre el código de React. Y me di cuenta de que es la función rendererRootSync. Y luego cambiaría al React profiler e intentaría responder cuáles son los componentes más costosos o componentes que se renderizan con más frecuencia? Y pasaría por todas o todas las renderizaciones grabadas y tomaría notas. Esto es siempre algo que hago cuando estoy perfilando personalmente. Simplemente miro todas las renderizaciones y tomo las notas. Así que hagamos eso. Oh, texto, espera, texto, acabo de.

Hagamos eso. Así que tenemos 15 rerenderizaciones, lo siento, amigo, no, rerenderizaciones. Y aquí está la primera renderización. Así que la primera rerenderización toma 50 milisegundos y rerenderiza el encabezado del editor, que toma nueve milisegundos, y toma, lo siento, renderiza el editor de widgets que toma 47 milisegundos. Realmente no necesito ir más allá de ellos, realmente no necesito averiguar qué está sucediendo exactamente más allá de estos componentes, qué se está renderizando dentro de ellos. En este punto, solo necesito entender cuáles son los componentes más costosos o cuáles son los componentes que se renderizan con más frecuencia? Así que simplemente voy a ir, cada renderización registra los componentes que se renderizan. Así que la segunda renderización, tomó 28 milisegundos, tomó 28 milisegundos, y renderizó la vista del panel de propiedades y la tabla. De nuevo, los números no se adaptan, no sé por qué, vista del panel de propiedades, fueron 28 milisegundos. Oops, 28ms, y la tabla, que tomó 20ms. Simplemente voy a eliminar estos números porque no se adaptan correctamente. Así que, bien, renderización tres. Renderización tres. Oh sí, aquí está el pequeño trozo de verde, transición. Tenemos alguna transición sucediendo, también podría cambiar al gráfico de rango para ver los componentes más costosos. Esto son solo componentes por sí mismos, no con hijos. Raramente lo uso, raramente es útil porque siempre quiero mirar cosas con hijos. Pero, bien, es solo alguna transición. Renderización tres, transición. Digamos, renderización cuatro. Renderización cuatro, lo que sucede aquí es que solo tenemos el editor de widgets. Y el editor de widgets toma 50 milisegundos. Así que, en este punto, creo que no voy a, o no sé, tal vez lo haré. Sigamos escribiéndolo así. Renderización cuatro, editor de widgets, 50 milisegundos. Veamos, renderización cinco, renderización cinco, vista del panel de propiedades de nuevo, 30 milisegundos, tabla 25 milisegundos. Así que, puedo simplemente copiar esto y actualizar los números. Vista del panel de propiedades, 30, 25. Y así, sigo pasando por todas las renderizaciones de esta manera, por todas las renderizaciones restantes.

Analizando Hooks y Hooks Personalizados en RackProfiler

Short description:

Analizamos el componente más costoso, el Editor de Widgets, que tarda casi 100 milisegundos en renderizarse. Investigamos por qué se vuelve a renderizar y encontramos que los hooks cinco y 47 cambiaron en la primera instancia, mientras que solo el hook número cinco cambió en la segunda instancia. Sin embargo, al examinar los hooks en el componente, solo encontramos 13 hooks. Esta discrepancia se debe a los hooks dentro de los hooks, que RackProfiler no reconoce. Para hacer coincidir los números de hook mostrados en RackProfiler con los hooks reales, podemos buscar hooks personalizados en el panel de componentes de Rack DevTools, donde los hooks personalizados se enumeran con sus números correspondientes.

Y sigo buscando, ¿cuáles son las partes más costosas en cada renderizado? ¿Por qué, qué es lo que más tiempo lleva? Como, aquí, de nuevo, tenemos su encabezado de editor en la renderización 11, por ejemplo. Y así, sigo de esta manera, y sigo resumiendo todos los componentes que se renderizan. Y una vez que he resumido cada renderización, miro el resumen, y encuentro el componente más costoso, el componente que corresponde al mayor tiempo de renderización. Y empiezo a depurarlo, porque es la parte más costosa, porque podríamos ahorrar más tiempo optimizándolo. Y en este caso, el componente más costoso es el Editor de Widgets. Son casi 100 milisegundos. Así que... Bien. Echemos un vistazo al Editor de Widgets. Intentemos averiguar por qué se volvió a renderizar. Así que Editor de Widgets... Podría hacer clic en el componente Editor de Widgets, y podría ver todas las instancias en las que se renderizó, y vería que se renderizó dos veces. La primera vez, se renderizó porque los hooks cinco y el número 47 cambiaron. Hooks cinco y 47. Y la segunda vez, se volvió a renderizar porque solo cambió el hook número cinco. Bien. Así que descubrimos por qué los hooks... Por qué se renderizó el componente. Ahora, empecemos a averiguar qué son estos hooks. Así que voy a ir al código... No, no, no, no, no. No mi nodo privado. ¿Se abrió? Bueno. Necesito código. Sí, eso no está bien. Así que. Lo que necesito, necesito el centro de wiki. Y necesito averiguar cuáles son los hooks número cinco y los hooks son número 47. Así que miremos el editor de widgets. Veamos todos los hooks que tienen. Así que tenemos el hook número uno, el hook número dos, el hook número tres. Cuatro, cinco, seis, siete, ocho, nueve, 10, 11, 12, 13. Y eso es todo. Tenemos número de hooks. Así que aquí hay otra pregunta para ustedes. Rack Dev tools nos dice que el componente se renderizará, el componente del editor de widgets se vuelve a renderizar porque su hook número cinco y 47 han cambiado. Pero si miras los componentes, si miras todos los hooks que tiene, solo encontrarías 13 hooks dentro de este componente. ¿Alguien tiene una idea de lo que está pasando? ¿Dónde está el hook número 47? ¿Qué pasó con los números de hook? ¿Por qué TrackProfiler muestra estos números?

Sí, son efectivamente hooks dentro de hooks. Así que un desafío, un desafío molesto con el RackProfiler es que cuando obtienes los números de hook, React no sabe nada, RackProfiler no sabe nada sobre hooks personalizados. Lo que RackProfiler sabe, es que tu componente tiene como 50 o 80 o quizás cien hooks incorporados de React que se están llamando. Pero si estos hooks están envueltos con algunos hooks personalizados, algunos hooks que vienen de React Redux, algunos hooks que vienen de tu propio código, algunos hooks que vienen de otros gestores de estado, RackProfiler no tendría idea de estos hooks. Y así cuando te muestra el hook número 547, es tu trabajo hacer coincidir estos números de hook con los hooks que realmente cambian en el código. Y hay varias formas de hacer esto. Así que la primera forma, la primera forma que siempre intento es tratar de encontrar estos números de hook no en el panel Profiler y no en el código, sino en el panel de componentes de Rack DevTools. Así es como lo hago. Si hago clic en el Componente de Control Widget Sage, ya está clicado y cambio al panel de componentes, este componente se enfocaría de nuevo. Y si miro a través del panel de hooks, vería que el panel de hooks dentro de los componentes, sí enumera todos mis hooks personalizados. ¿Puedo poner esto uno al lado del otro? Intentemos poner esto uno al lado del otro. Espera, voy a mover Zoom por poderes. No puedes verlos, pero yo sí. Y cubren estas cosas. Así que aquí, mira, ¿correcto? El panel de componentes, sí reconoce los hooks personalizados. Me muestra el hook de selección de widget de uso. Me muestra los hooks de uso de párrafo, uso de despacho selecto, uso de selector, uso de selector, uso de selector, uso de selector, uso de selector, uso de diseño de aplicación dinámica. Y luego algunos hooks incorporados, uso afectado, uso afectado, uso afectado y uso de devolución de llamada. Y si abres cualquiera de estos hooks, lo que verías es que verías números junto a cada hook incorporado de rect que se está llamando. Incluso si estos números ocurren varios niveles abajo en el árbol de hook personalizado. El único hook que no obtiene números es el hook de contexto. Y hay una buena razón para ello. Está implementado de manera diferente. Y hay una charla sobre ello todo en Rects en Ámsterdam. No recuerdo el nombre de la charla, pero si me preguntas en el chat podría encontrarlo. Pero sí, si expandes todos estos hooks, verías los números. Y esa es una forma de hacer coincidir los números que Rect Profiler te dice con los hooks reales. Es molesto. Sí, no hay una mejor manera que yo sepa. Es un poco engorroso, pero hagámoslo. Así que voy a hacer una captura de pantalla de esto. Lo voy a poner en la pantalla para poder compararlo con el panel de componentes. Y veamos, necesitamos encontrar el hook número cinco.

Uso de Why Did You Render para la depuración de rendimiento

Short description:

El React Profiler a veces muestra números de hook incorrectos debido a un error. Para superar esto, utilizo una herramienta llamada Why Did You Render. Me ayuda a entender por qué se renderizan los componentes y qué hooks y props han cambiado. Al habilitar Why Did You Render, puedo ver los cambios en el componente Editor de Widgets y hacerlos coincidir con hooks específicos. También puedo usar el depurador para establecer puntos de interrupción y determinar qué selector cambia realmente. Esta herramienta es invaluable para la depuración de rendimiento y proporciona información más precisa que el React Profiler.

Y el número de hook cinco parece provenir de mi primer use selector. Use selector, aquí está. Entonces este hook tiene el número de hook cinco. Está bien. Oh, guardé y se recargó. Eso es desafortunado. Que se dijo, vamos a encontrar qué lado comenzar. Y luego el número de hook 47, vamos a encontrar, no, no aquí, no aquí. Oh sí, aquí está. Número de hook 47. Entonces el número de hook 47 vive aparentemente dentro del diseño de la aplicación dinámica. Y aparentemente es un hook de useEffect. Que es, ¿te asfixias, te asfixias, te asfixias, te asfixias, el segundo antes del último useEffect, hook 47. Y si estás mirando esto y te preguntas, está bien, pero ¿por qué exactamente, cómo exactamente cambia? ¿Qué está pasando realmente aquí? Esto realmente no tiene mucho sentido para mí. Tengo un buen comentario para ti, que es que tampoco tiene mucho sentido para mí, así que un problema y otro error con las React DevTools, con un React Profiler, desafortunadamente, es que aunque es en su mayoría preciso al mostrar los números de hook, a veces los números de hook se desvían. Nunca tuve suficiente tiempo o suficiente voluntad para ir e intentar averiguar qué es exactamente lo que está causando esto y por qué exactamente los números de hook se desvían, pero cuando tienes suficientes hooks en el componente, lo que sucede a veces es que React empieza a contar mal y empieza a mostrarte el número de hook 47, o en realidad significa el número de hook 49 o el número de hook 40-algo, y mientras que este primer enfoque va al panel de componentes y hace coincidir los números de hook funciona bien en aplicaciones simples, no es infalible, desafortunadamente, debido a este error en aplicaciones personalizadas. En, lo siento, en aplicaciones personalizadas, en aplicaciones grandes porque los números de hook se desvían, y es por eso que aparte de hacer esto lo que siempre hago es que hago coincidir esto con otro enfoque para encontrar los hooks correctos, los hooks correspondientes. Utilizo una herramienta llamada Why Did You Render. Mi pregunta para ustedes, amigos, ¿alguno de ustedes ha usado Why Did You Render antes o ha oído hablar de Why Did You Render? ¿Podrían simplemente enviar un más al chat si han usado o escuchado la herramienta que se llama Why Did You Render? Veo un más y veo algunos menos. ¿Alguien más? Está bien, entonces Why Did You Render es una biblioteca de terceros que podría conectar en mi aplicación de React y esta biblioteca me diría exactamente por qué cada uno de mis componentes se renderiza, incluyendo cuáles de los hooks han cambiado, cuáles de las props han cambiado, y cómo exactamente estas props y estos hooks han cambiado. Está disponible en WellDoneSoftware.yd para renderizar en GitHub. Y ya tengo esta herramienta instalada en el repositorio, así que ahora solo necesito habilitarla. Entonces, voy a ir a widgets-editor-slash-index.ts6. Y voy a descomentar esta línea que dice descomentar para habilitar yd2-render. Y yd2-render está configurado de esta manera. Es el código de inicio de la lectura. Podrías leer el readme y podrías hacer esto en tu aplicación. Pero si haces esto, y si vas a cualquier componente que estás perfilando, y si agregas tres líneas más de código, widgets-editor.yd2render, igual, bloquear en valor diferente verdadero, lo que obtendrías es, además del rect profiler, además de todo lo que muestra el rect profiler, obtendrías esto. yd2render instrumentaría cada renderizado del editor de widgets, y yd2render miraría, cada vez que algo dentro de ese componente cambia, y así yd2render miraría todos los widgets que han cambiado, y mostrará cómo exactamente han cambiado. Y verías que, mira, hook, tu selector ha cambiado. Con estos valores, meanHeight cambiando de 700 a 100, o Children cambiando de este array a este array, UnbiddenPaths cambiando de este array a este array, te mostrará cada cambio que sucede en el componente que estás tratando de inspeccionar. Y esto es realmente, realmente conveniente. Cuando tengo algunos componentes, como Widget Editor en este caso, que estoy tratando de averiguar, está bien, ¿por qué exactamente se está renderizando, a menudo miraría en el panel de performance, en el panel del profiler, pero luego iría y habilitaría Widget Editor para renderizar, y comenzaría a inspeccionarlo con Widget Render. De todos modos, veamos cómo funciona Widget Editor Render y por qué ayuda a Render a perfilar esta interacción. Entonces, lo que hemos descubierto hasta ahora es si voy al, si tengo esta aplicación compleja del mundo real con alguna interacción que está siendo lenta, lo que podría suceder, lo que a menudo sucedería es que reportaría una traza de performance, y vería no una sino varias cosas sucediendo. Y si todas estas cosas o la mayoría de estas cosas suceden en Rect, iría al Rect profiler y grabaría lo que está sucediendo con Rect profiler, y también vería no una sino varias renderizaciones sucediendo. Siempre que perfiles una aplicación compleja del mundo real, eso es algo que verías. Y entonces el siguiente paso, cuando estás perfilando, cuando estoy perfilando la aplicación del mundo real y me doy cuenta de que la mayor parte del tiempo se gasta en el código de Rect, es que simplemente repaso cada renderizado y si encuentro los componentes más costosos, y luego trato de averiguar po

Depuración de Cambios de Selectores

Short description:

Para depurar cuando un nuevo selector cambia, añade un punto de interrupción condicional para comparar el nuevo selector con el nombre de la variable hook. Cuando se cumple la condición, el depurador pausará la ejecución en esa línea. Al examinar la pila de llamadas, puedes rastrear la línea exacta y el selector que cambió. Este método es especialmente útil para componentes complejos con múltiples selectores.

Entonces, la condición que quiero que sea verdadera es que quiero que el depurador se detenga cuando un nuevo selector cambia. ¿Correcto? Y entonces, si miro los registros de la consola, si miro los registros de la consola, vería que lo que esta línea bloquea hook, luego mi nombre de hook, el resultado. Por lo tanto, quiero pausar el depurador cuando ¿por qué renderizaste los registros, hook, nuevo resultado del selector? Porque solo me importan los nuevos selectores. Podría ser el estado usado, podría ser cualquier otra cosa. Entonces, voy a añadir un punto de interrupción condicional que comparará un nuevo selector con aparentemente el nombre de la variable hook. Entonces, cuando el nombre del hook, triple igual a tu selector, Chrome ahora pausará la ejecución en esta línea. Y entonces, espera, sígueme, seleccionaré el texto y Chrome pausará la ejecución en esta línea. También podría revisar la consola, podría ver que ¿por qué lo renderizaste comenzó a registrar lo mismo que estaba registrando antes, ¿verdad? Acabamos de decir que ya está escrito debido a un cambio de hook, todavía no ha registrado esta línea porque nos detuvimos en ella. Pero, espera, ¿dónde está el método del depurador o tech? Sí, aquí está. Si miro la pila de llamadas y si empiezo a subir por la pila de llamadas, arriba, arriba, arriba, arriba, arriba hasta que salgo de ¿por qué lo renderizaste al código real que pertenece a mi aplicación, lo que vería es que vería la línea exacta que cambió el selector exacto que cambió el selector exacto que se registró en la consola porque cambió. Y esto es extremadamente conveniente cuando tienes un conjunto complejo, cuando tienes un componente complejo con como 10, 15 selectores. Esto es súper conveniente para hacer coincidir. Ojalá hubiera una mejor manera. Es una forma bastante engorrosa pero esto es extremadamente conveniente para hacer coincidir el selector exacto, el cambio exacto al selector exacto u otro hook exacto.

Depuración de Aplicaciones Complejas y Escritura Lenta

Short description:

Aprendimos cómo depurar aplicaciones complejas y reales grabando con herramientas de desarrollo, identificando componentes costosos y optimizando la renderización. En la tercera parte, discutiremos las interacciones lentas con grandes nodos y cómo afectan el rendimiento de la escritura.

Entonces, esto es lo que aprendimos. Aprendimos que solo necesitamos hacer renders porque los hooks de widgets son cinco. Aparentemente, este es el selector de usuario de widgets. Renders. Todavía está el número de hook 47, tal vez no sea el 47. Podría ser un número incorrecto. Tal vez las RegDefTools cuentan mal. Pero si continúo la ejecución, entonces las RegDefTools se detendrían de nuevo y seguiría subiendo varios niveles una y otra vez hasta llegar a mis códigos. Y llegaría a mi código. Llegaría a un hook llamado UseDynamicAppLayout, que se llama desde Widgets Editor, se llama aquí. Y luego UseDynamicAppLayout llama al CanvasWidgetUseSelector. Y ese es otro hook que cambia. Entonces CanvasWidgetUseSelector dentro de UseDynamicAppLayout. Y luego continúo. Y de nuevo, me detuve en el mismo punto de interrupción y subo varios niveles más hasta llegar al Widgets Editor, y veo mi WidgetsUseSelector de nuevo. Y esto coincide con lo que vieron solo ejecutando una rápida comprobación de cordura. ¿Esto coincide con lo que vi en el Rack Profiler? Esto parece coincidir con lo que vi en el Rack Profiler porque no pueden cambiar tres hooks. Dos de ellos eran idénticos. Y el primer hook fue el WidgetsUseSelector y el tercer hook que cambió también fue el WidgetsUseSelector. Entonces, hasta ahora todo bien. Y... Sí. Entonces esto es lo que hago. Esto es lo que hacen para debug este caso. Esto es lo que hacen para debug esta interacción. Esto es lo que hago para debug este componente concreto. Y una vez que descubro qué hooks están cambiando realmente, voy a intentar encontrar una forma de optimizar este selector de uso. Y nuestra masterclass no cubre eso, pero podrías hacer algunas cosas. Podrías hacer, no sé, podrías optimizar tu selector en sí. Tal vez podrías hacer algunos de mis selectores. Podrías hacer una comparación de igualdad profunda. Puedes hacer muchas cosas para optimizar esto, pero este es generalmente el proceso que sigo con aplicaciones reales complejas y reales. Empiezo grabando cosas con las herramientas de desarrollo y miro si es principalmente código rect o código no rect o tal vez algo más. Y si es principalmente código rect, veo si es la renderización rect, que en este caso lo fue de nuevo. Y trato de averiguar cuáles componentes son los más costosos y simplemente tomo notas, como esta. Y luego, una vez que encontré los componentes más costosos, intenté averiguar por qué se renderizaron usando las herramientas rect, usando por qué renderizaste. Y luego intenté averiguar cómo hacer que se rendericen menos a menudo o renderizar menos de ellos o etc. Entonces es básicamente el mismo proceso, es el mismo proceso para aplicaciones simples. Es el mismo proceso para grandes aplicaciones. Es solo que con grandes aplicaciones necesitas repetirlo una y otra y otra y otra vez hasta que hayas resuelto todas las interacciones costosas, componentes costosos.

Entonces esta fue la segunda parte de la ructura. Miramos una aplicación del mundo real. Perfilamos la aplicación del mundo real con las herramientas Chromative y el perfilador rect. Miramos por qué renderizaste. Que nos muestra qué componente, por qué exactamente se renderizaron los componentes. Es una herramienta muy conveniente. Me gusta mucho, nos muestra qué cambia dentro de los selectores, dentro de los hooks. Y vimos cómo hacer coincidir el hook cambiado dentro del perfilador rect con el código real. Puedo hacer esto usando el panel de componentes rect, que es preciso en tal vez el 90% de los casos. Y puedo usar esto usando wide para renderizar, que es un poco más engorroso, pero es 100% preciso. Genial.

Entonces en la tercera parte de la masterclass, hablaremos sobre los efectos, que también pueden hacer que tu aplicación sea lenta y sobre algunas otras cosas. Entonces echemos un vistazo a otra interacción lenta en nuestra primera aplicación. Entonces una interacción que perfilamos y vendimos fue la escritura lenta en los nodos cuando tienes muchos nodos. Pero aquí hay otro caso extremo, otra situación cuando ocurre este problema. Digamos que solucionamos este problema y desplegamos el código a producción e hicimos el anuncio de que mira, no entrar, no escribir, ahora es rápido. Pero algunos usuarios todavía llegaron a los comentarios y fueron como, hey, todavía es lento para mí. Y fuiste a investigar y descubriste que estos usuarios tienen una configuración diferente. Específicamente, en lugar de tener un montón de nodos regulares, tienen varios realmente, realmente, realmente grandes nodos. Y luego cuando escriben en cualquiera de los nodos no relacionados, pueden tener tantos nodos como necesiten, pero si tienen muchos... Lo siento, si tienen varios nodos enormes, lo que sucede es que la escritura es de hecho lenta. A pesar de la solución que hemos hecho, cuando tienes nodos enormes en tu aplicación, la escritura sigue siendo lenta. Entonces intentemos reproducir este caso. Voy a crear tal vez 20 nodos enormes, y voy a hacer clic en Agregar un nodo. Y ahora tengo como 20 nodos que son realmente, realmente grandes, ¿verdad? Pero ninguno de ellos está enfocado. Este nodo es enorme, pero no está enfocado. Solo voy a abrir un nodo pequeño, y voy a intentar escribir en este nodo pequeño. Y mientras escribo en este nodo pequeño, notaría de nuevo que la escritura es lenta. Entonces mira, estoy escribiendo, y el hilo principal se vuelve completamente rojo. Estoy escribiendo más, y se llena de rojo de nuevo.

Depuración de Rendimiento con Profiler

Short description:

Para depurar problemas de rendimiento, comienza grabando la interacción en el panel de rendimiento. Busca picos de actividad de la CPU que correspondan a interacciones lentas. Amplía el código y analiza el código de desarrollo rag dom. Evita saltar al profiler de inmediato, ya que puede no mostrar los efectos que se ejecutan después del renderizado. El profiler wrap solo muestra el tiempo que se pasa volviendo a renderizar los componentes, no los efectos. Esto puede llevar a malentendidos sobre los problemas de rendimiento reales.

Entonces, mucho trabajo, y sí, se siente lento. Entonces, ¿cómo hacemos para debug esto? ¿Cómo perfilamos esto? Entonces, mi primer paso siempre es, voy al panel de performance, volvamos a cambiar esto al modo claro que tuvimos durante toda la masterclass. Voy al panel de performance, y hago clic en grabar. Y grabo la misma interacción una vez, dos veces, tres veces, y paro. Y luego miro a través de la grabación. Veo de nuevo, tres picos de actividad de la CPU que corresponden a mi escritura en el editor. Entonces, este es uno, y luego este es dos, y este es tres. Y amplío el primero, y empiezo a mirarlo. Y de nuevo, noto algún código de desarrollo rag dom, etcétera, etcétera. Entonces, de nuevo, mucho código rag dom, ¿verdad? Entonces, en este punto, podría pensar, es hora de cambiar al profiler e intentar grabar esto con un profiler. Pero, y esto es lo que he estado haciendo hasta ahora. Sí. No te equivoques. Esto es lo que he estado haciendo hasta ahora. He estado saltándome un paso muy importante. De hecho, si haces esto, si haces esto cada vez que tienes algún problema de performance, si ves algún código rag dom y saltas al profiler de inmediato, cometerías un error. Porque si hago esto ahora, si cambio al profiler y si intento grabar esta interacción usando el profiler wrap, la grabo una vez y paro la grabación. Lo que vería es que tuve un renderizado y este renderizado tardó 26 milisegundos y dentro de la cadena renderizada solo se renderizó el AppComponent y el AppComponent tomó estos 26 milisegundos. Pero lo que quizás no note es que mientras el renderizado tardó 26 milisegundos, los efectos que se ejecutan después del efecto han, después de que se ha realizado el renderizado tardaron 10 veces más tiempo. Tomaron 300 milisegundos. Y el profiler wrap, no muestra los efectos en absoluto. Solo muestra el tiempo que los componentes pasaron. Lo siento, que los componentes pasaron volviendo a renderizar. Si algún componente tiene renderizadores costosos, el profiler wrap no mostraría esto en la vista de la industria en absoluto. Y aún peor.

Analizando los Efectos de React

Short description:

Gente, ¿quién de ustedes todavía usa React 16 y React 17? ¿Podrían enviar su versión actual de producción de React al chat? Algunos de ustedes están en Rect 17 y con Rect 17, esto es aún más complicado porque con Rect 18 al menos podrías ver, podrías notar que, hey, el Reactor de Efectos Pasivos y los Efectos Pasivos y los Efectos Pasivos tomaron algo de tiempo. Pero si usas, si por alguna razón usas Rect 17, si aún no has actualizado a Rect 18, lo que sucedería es que vería la duración del renderizado, pero no vería la duración del efecto en absoluto. Y esto podría ser muy confuso. Mientras vea que el código de React sigue ocupando la mayor parte del tiempo y sigue ocupando la mayor parte del tiempo, 50 milisegundos más 315 milisegundos. Es casi la duración completa de este evento de pulsación de tecla. Mientras vea esto, podría simplemente mirar el evento, podría mirar las funciones de nombre y podría averiguar qué es exactamente lo que está sucediendo en el código de React. Aquí hay una hoja de trucos muy bonita que tengo para esto. Una referencia interna de React. Esto es cierto para React16, React17, React18, cualquier versión de React que uses. Así que render root sync significa que tú, el director está ocupado renderizando algunos componentos. Tenemos los efectos de diseño de commit, que ejecutan el componente de uso del efecto de diseño montado y el componente que se actualiza. También tenemos la función que se llama flushBaseEffect, que en la referencia es la función que ejecuta useEffect. Y lo que esto significa es que no puedo ir al Profiler de React y averiguar qué está pasando aquí. En cambio, necesito seguir avanzando en el gráfico de llamas hasta que deje el código de React y me encuentre con el efecto real que se está ejecutando. Y es bastante fácil de encontrar, tiene un color diferente. Y si lo encuentro, si hago clic en él, vería que aquí, aquí está este efecto. Use effect, save nodes to local storage. Muy bien, así que hemos encontrado al culpable, hemos encontrado el efecto costoso. ¿Cómo lo hacemos más barato? Entonces, en este punto, hay dos formas de analizarlo. Lo primero que podría intentar averiguar es por qué se vuelven a ejecutar estos efectos. ¿Realmente necesita ejecutarse el efecto o es solo su tasa de dependencias que está cambiando innecesariamente? Tal vez también estamos pasando alguna función que cambia cada vez.

Gente, ¿quién de ustedes todavía usa React 16 y React 17? ¿Podrían enviar su versión actual de producción de React al chat? Me pregunto, ¿quién de ustedes está en el 18? ¿Quién todavía usa el 16? ¿Quién todavía usa el 17? ¿Podrían enviarlo al chat? 17, 17, 18, 18, 18, 18, 18, 17, 18. Oh sí, entonces, bien. Muchos de ustedes ya están en el 18. Sigo preguntando esto durante cada masterclass que hago y veo cómo cada vez más personas actualizan al 18. Esto es fascinante. Muy bien, pero algunos de ustedes todavía, ooh, AngularJS 1x. Bueno, lo siento por eso. Mis condolencias. De todos modos, algunos de ustedes están en Rect 17 y con Rect 17, esto es aún más complicado porque con Rect 18 al menos podrías ver, podrías notar que, hey, el Reactor de Efectos Pasivos y los Efectos Pasivos y los Efectos Pasivos tomaron algo de tiempo. Pero si usas, si por alguna razón usas Rect 17, o no, lo siento, no por alguna razón, si usas Rect 17, si aún no has actualizado a Rect 18, lo que sucedería, está bien, voy a cambiar a Rect 17, uso Rect 18 falso y comento con la misma parte que no existe en Rect 17. Entonces, si cambio a Rect 17, recibo esta advertencia que codifiqué personalmente y vuelvo a grabar la misma interacción usando Rect Profiler, oh, y stub, espera ahora, oh, recarga. Oop, y stub. Espera, esto. Oh no, no cambié a, ¿qué hice mal? ¿Qué hice mal? Oh sí, correcto, necesito reiniciar el servidor VEED porque todavía usa Rect, Rect 18. Entonces, si cambio completamente a Rect 17 en esta aplicación, o si todavía estás usando Rect 17, si intento grabar la misma interacción usando Rect Profiler, lo que vería, vería la duración del renderizado, pero no vería la duración del efecto en absoluto. Y esto podría ser muy confuso porque a menos que entre y haga coincidir directamente lo que veo, espera, a menos que entre y haga coincidir directamente lo que veo en el panel de performance, con el panel del profiler, y a menos que note que el panel del profiler me dice que son 25 segundos, lo siento, milisegundos, pero el panel de performance en realidad me dice que la interacción tomó 350 milisegundos. A menos que note esto, lo que podría suceder es que miraría este componente y trataría de optimizar los componentes más costosos como lo hemos estado haciendo en las últimas dos horas, y eso no me daría ningún beneficio. Porque esto solo es responsable de como el 10% del costo total de la interacción. Entonces, por eso, por eso, allí en el gráfico de llamas, hay un paso más que he estado saltando hasta ahora. Que es cada vez que grabo alguna interacción usando Rack Profiler, lo siento, usando Chrome DevTools, lo que necesito verificar es, no solo necesito verificar si es principalmente código de React o principalmente algo más. También necesito verificar si es renderizado de React o si son efectos de React. Y voy a volver a React 18, yarn add, React 18, yarn start, y voy a grabar esto de nuevo con React 18. Esto es un wrap, F, y stop. Y tendría que mirar a través de mi grabación e intentar averiguar qué es exactamente lo que está sucediendo aquí y dónde exactamente React pasa la mayor parte de su tiempo, si es en el renderizado o si es en el efecto. Entonces, veamos qué está pasando aquí. Obtenemos el evento de keepers, el evento de keepers desencadena el evento de entrada de texto, entrada, etc. Luego obtengo algunas llamadas del espejo de código, anónimo, entrada de área de texto, encuesta, yada, yada, yada, yada, yada, como todo este código, realmente no me importan todas estas funciones, solo ejecutan las funciones secundarias, ¿verdad? No pasan mucho tiempo en su propio, es como, son principalmente solo estructuras para otras funciones. Entonces, sigo avanzando, veo algunos anónimos de index JS 6. Muy bien, esto parece mi código. Obtenemos algo de React, es algo de React y obtenemos algún controlador de eventos. Y luego llamamos a save node, luego llamamos a save node de nuevo, y finalmente llegamos al código de React. Y entonces save nodes se divide en dos rectángulos, llama a dos funciones, una dispatch set, state y otra anónima. Si sigo adelante, la segunda anónima, entonces es algo de código de React Redux, y luego de nuevo llegaría a React en desarrollo. Y entonces, en este punto, si es solo, si nunca llega a los códigos de React, entonces son estas marcas, entonces es principalmente código no React, entonces necesito averiguar qué está pasando realmente allí. ¿Cuáles son las funciones más costosas? Pero mientras vea que el código de React sigue ocupando la mayor parte del tiempo y sigue ocupando la mayor parte del tiempo, 50 milisegundos más 315 milisegundos. Es casi la duración completa de este evento de pulsación de tecla. Mientras vea esto, podría simplemente mirar el evento, podría mirar las funciones de nombre y podría averiguar qué es exactamente lo que está sucediendo en el código de React. Y aquí hay una hoja de trucos muy bonita que tengo para esto. Una referencia interna de React. Esto es cierto para React16, React17, React18, cualquier versión de React que uses. Así que render root sync significa que tú, el director está ocupado renderizando algunos componentes. Si te desplazas más abajo en los gráficos de llamas, incluso podrías ver estos componentes. Podrías ver el componente de lista de notas que se está renderizando. Eso es solo la función de lista de notas que se está llamando, ¿verdad? Podrías ver el botón de nota que se está renderizando. Podrías ver algo de React markdown que se está renderizando. Botones de grupo de botones. Entonces, podrías ver todo esto. Podrías ver todos los componentes que se están renderizando más abajo en el gráfico de llamas. Luego, los efectos de diseño de commit son la parte que se ejecuta, usa el efecto de diseño del componente montado y el componente que se actualiza. No parece que lo tengamos aquí. Tenemos el commit root. Oh no, sí lo tenemos. Aquí están los efectos de diseño de commit. También tenemos los efectos de mutación de commit, qu

Analizando las Dependencias de useEffect

Short description:

Para rastrear qué valores se actualizan en sus componentes, puede utilizar una herramienta llamada useYDTOBlade. Le permite ver las dependencias exactas de un useEffect que cambia. En este caso, la dependencia de los nodos cambia mientras se ejecuta el useEffect. Sin embargo, no es posible evitar que los nodos cambien en este escenario. La función getNodes no es el cuello de botella, y usar una función anónima o la función de recurso no resolvería el problema. ¿Alguna otra idea sobre cómo optimizar esto?

Quizás solo necesitamos usarMemoria o algo de callback, ¿verdad? Así que intentemos averiguar eso. Tenemos nuestro useEffect que tarda 300 milisegundos en ejecutarse y cambia porque cambió su prop de nodos y cambió las props de ID de nodo activo. Entonces, en este caso, todas estas props están definidas justo aquí, ¿verdad? Es muy fácil ver lo que significan y lo que hacen pero si esta fuera una aplicación más grande, si hay múltiples niveles de indirectas, entonces esto sería más difícil de ver. Y una herramienta que realmente me gusta usar para esto para averiguar qué dependencias han cambiado es una herramienta llamada useYDTOBlade. Así que si buscas en Google useYDTOUpdate. Creo que antes tenías solo un ejemplo copiable y pegable. Ahora son todas dependencias. No me gustan las dependencias. Era muy conveniente antes. De todos modos, hay un montón de hooks llamados useYDTOUpdate y podrías instalar alguna biblioteca para tener ese hook pero hasta hace unos meses, había un sitio web que te daría solo el código copiable y pegable que podrías copiar y poner en tu aplicación y luego usarlo así para rastrear qué valores se actualizan en tus componentes. Y realmente me gusta esto porque no necesitas instalar nada, solo copias y pegas, es muy conveniente. Lo voy a lamentar. Oh, no, se recargó de todos modos. Bueno, lo que sea. Vamos a mi aplicación / useEffect. Voy a devolver el seguimiento al equipo. Así que voy a ir a la aplicación índice solo seis y aquí está mi useEffect. Y quiero ver cuál de estos valores realmente cambia. Entonces, lo que voy a hacer es simplemente pegar el hook que acabo de copiar. Se hace referencia aquí en el diagrama de flujo o podrías simplemente instalar um instalar en tu biblioteca que lo tiene. Y voy a llamar a este hook así. Vamos a llamar más cualquier cadena que identifique este registro. Digamos que es app useEffect. Y voy a pasar los valores que quiero rastrear. En este caso, por defecto, son props, por defecto se usa para rastrear qué props cambian. Pero puedes usarlo para cualquier cosa. Y en este caso me importan los nodos y los valores de ID de nodo activo, que son los parámetros en este useEffect. Genial. Entonces, veamos, veamos qué hace. Así que voy a abrir el nodo y voy a escribir en los nodos. Y dicen que escribo en el nodo una vez, dos veces, tres veces. Veo los registros de qué ID actualizar, que me muestran el valor exacto, la dependencia exacta de este useEffect que cambia. Y podría ver que las dependencias exactas de este useEffect que cambia es la dependencia de los nodos. Y esta dependencia de nodos cambia de este sujeto a este sujeto. Así que incluso podrías copiar, hacer clic en esto y almacenar objetos como una variable global. Y también hacer clic derecho en el segundo y también almacenar objetos como la variable global. Y luego podría compararlos en profundidad o hacer lo que quiera con ellos. Temp uno, temp dos, como no son iguales, ¿verdad? Los nodos han cambiado. Entonces, los nodos cambian este parámetro mientras se ejecuta useEffect. Entonces, mi pregunta para ustedes, ya hemos visto que este objeto de nodos cambia, ¿podemos optimizar esto? ¿Podemos realmente optimizarlo? ¿Podemos hacer algo al respecto? ¿Podemos evitar que estos nodos cambien? Y si sí, ¿cómo, y si no, por qué? ¿Podemos hacer que estos nodos? Entonces, como estoy escribiendo en los nodos, estoy escribiendo en el editor de nodos, ¿verdad? Y luego se ejecuta useEffect. El equipo sugiere cambiar los nodos. ¿Cómo exactamente deberíamos cambiarlos? Entonces, primero en silencio y sugiere que podría ser más rápido. Sí, entonces creo que necesitamos pasar como una función anónima, ¿verdad? Para, no estoy seguro si eso está causando el problema, pero sí. Eso es en realidad un gran punto. Entonces, como ahora estamos ejecutando nodos todo el tiempo, ¿verdad? Y esto llamaría a un sorteo, esto haría que se ejecute solo una vez cuando se ha creado el componente. Entonces, no, esto no es el cuello de botella, esto no es un cuello de botella. Si esto fuera un cuello de botella, entonces veríamos que la función get node en sí misma es costosa. O, lo siento, hay dos formas en que esto podría ser un cuello de botella. La primera forma es si la función get node fuera costosa, entonces simplemente veríamos eso en el rastro. Otra forma en que esto podría ser un cuello de botella es si useState tomaba este valor y establecía nodos a este valor cada vez, ¿verdad? Por eso sugeriste usar esa función de recurso. Así que esto no es lo que está pasando. UseState solo usa el valor que devuelve get nodes durante el primer renderizado, luego simplemente lo ignora. Entonces, sí, esto no ayudaría. Pero gran sugerencia. ¿Alguna otra idea, gente? Tenemos un useAffect que se ejecuta en cada pulsación de tecla porque cambia el objeto de nodos. ¿Podemos evitar que cambie? Y si sí, ¿cómo? Y si no podemos evitar que cambie, entonces ¿por qué? ¿Alguna idea? Está bien si adivinas mal. Podría ser complicado. Solo una suposición salvaje. Sabes que ese bloque useAffect, tienes dos... Dos cosas allí. ¿Es posible separarlos? No sé si eso es lo que... Causando el problema, porque no sé lo que hace esa función. Oh sí. Sí, sí, sí, sí. Esa es una buena idea. De hecho es posible. Estás pensando en la dirección correcta. No creo que ayudaría aquí. Veamos lo que realmente hace el safeNodeToLocalStorage.

Analizando la Guarda de Nodos y Optimizando useEffect

Short description:

Podemos equilibrar el proceso de guardado de nodos desvalorizando el guardado de nodos en LocalStorage en cada pulsación de tecla y en su lugar guardándolos cuando el navegador está inactivo o el usuario ha dejado de escribir. Sin embargo, no podemos eliminar el hook useEffect o reemplazarlo con useMemo en este caso. El sujeto del nodo cambia a medida que escribimos en el editor de nodos, y necesitamos guardar los nodos en el almacenamiento local cada vez que cambian. Para optimizar el efecto, podemos analizar la grabación de rendimiento e identificar la función marcada como la parte más que consume más tiempo. Llamar a marked en cada nodo es costoso debido al tamaño de los nodos y al proceso de análisis. Podemos considerar alternativas como eliminar marked, encontrar una biblioteca más barata, o optimizar el proceso de conversión. Para medir la duración de cada iteración de bucle, podemos usar la función console.time, que inicia y detiene un temporizador y registra la duración en la consola. Esto nos permite identificar las iteraciones más costosas y optimizar en consecuencia.

Doo, doo, doo, doo, doo. Opción de comentario. Entonces, safeNodeToLocalStorage. Toma el... Vamos, hazte más grande. ¿Por qué no puedo, oh sí. Toma el sujeto del nodo. Toma el ID del nodo activo, transforma el objeto del nodo, serializa cada nodo de los nodos. Lo transforma en algún formato medible, y luego lo convierte en cadena, y luego lo guarda en LocalStorage. Así que, teóricamente, podrías dividirlo, porque el ID del nodo activo es independiente de los nodos, sí, están simplemente establecidos de forma independiente. Pero, porque el ID del nodo activo es, así que puedes ver que hay un montón de lógica que guarda los nodos, ¿verdad? Y luego hay solo una línea, que establece el siguiente ID de nodo. Entonces, pero, así que definitivamente podrías separarlos, y eso podría funcionar en algunos casos. En este caso, todavía no funcionaría, porque es el sujeto del nodo el que cambia cada vez. El ID del nodo activo no cambia, así que no importa si lo separamos o no. Qwinkly sugiere equilibrar los nodos, y ese es un gran enfoque, sí. Si desvalorizamos el guardado de nodos, si desvalorizamos guardar nodos en LocalStorage, no necesitamos guardar nodos en LocalStorage en cada pulsación de tecla, ¿verdad? Podemos hacerlo cuando el navegador está inactivo, podemos hacerlo cuando el usuario ha dejado de escribir, así que podemos simplemente equilibrarlo. Esa es una solución increíble, sí. Ikor pregunta, ¿podemos deshacernos de useEffect y usar useMemo? No estoy seguro exactamente de cómo, pero si tienes una idea, como un fragmento de código que podría funcionar aquí, por favor, que crees que podría funcionar aquí, no dudes en sugerirlo. No estoy muy seguro. Sí, no estoy muy seguro de cómo reemplazar esto con useMemo. Pero de todos modos, la idea clave, la idea central aquí es que, en este caso, el sujeto del nodo cambia porque almacena todos los nodos, y cambia porque estoy escribiendo en el editor de nodos. Así que estoy escribiendo aquí el sujeto del nodo cambia, y eso hace que se ejecute el useEffect. Realmente no hay nada que podamos hacer al respecto. Tiene que cambiar. Almacena los objetos, y tenemos que guardar los nodos en el almacenamiento local cuando los nodos cambian. Así que este es el paso. ¿Por qué tiene que ejecutarse esto? Hemos descubierto por qué se ejecutan, y no somos capaces de optimizar esto. Así que el siguiente paso es el paso final, es que solo necesito volver a Ractor Filer, y necesito tratar de averiguar cómo puedo hacer que este efecto, cómo puedo llamar a este efecto menos abierto, que es lo que Quimic sugerimos, podríamos debilitarlo, o cómo puedo hacer que ese efecto sea más barato? Y aquí hay un último truco que me gusta usar, un último truco que quería mostrarles hoy. Así que si voy al panel de performance, y yo, veamos, veamos, así que aquí está save nodes to local storage, nuestro, así que aquí está nuestro efecto, ¿verdad? useEffect. Toma 300 milisegundos. Todo el tiempo en el useEffect es tomado por la función saveNodes a local storage. Ahora, lo que está pasando dentro de ese saveNodes a la función de almacenamiento local es que simplemente tenemos un montón de códigos corriendo así. Así que tenemos transformer nodes. Así que creamos el objeto transformerNodes. Luego caminamos sobre cada nodo. Creamos un objeto transformerNode que simplemente toma el nodo original, añade la propiedad HTML, marked parse, y toma la fecha, simplemente convierte la fecha, analiza la fecha de lo que sea, de como la fecha, lo siento, como una cadena ACO. Y luego asigna el objeto. Luego convierte el objeto en cadena. Y luego lo guarda en local storage. Y si miras en la grabación de performance, lo que, oops, déjame hacerlo más estrecho, lo que vería es, vería que la mayor parte del tiempo aquí se gasta ejecutando el código marcado. Así que tenemos un montón de nodos, tenemos 20 nodos enormes, y lo que hacemos aquí es que llamamos a un parse marcado en cada nodo. Y marked parse, marked es una biblioteca que toma markdown y lo convierte en HTML. Así que llamar a marked en cada uno de estos nodos es aparentemente costoso porque, bueno, los nodos son enormes y analizarlos lleva un tiempo. Y entonces, bueno, una forma de optimizar esto es quizás deshacerse de marked o como para deshacerse de la conversión o tratar de encontrar una biblioteca más barata o hacer algo más. Pero antes de eso, si quisieras averiguar cuáles de estos nodos son los más caros, ¿dónde pasa el navegador la mayor parte del tiempo llamando a marked parse en cada nodo? ¿En qué iteración de bucle el navegador pasa más tiempo? ¿Cómo harías eso? Mi pregunta para ti. ¿Cómo harías, cómo podrías hacer, cómo mides cuánto tiempo lleva cada iteración? Porque el profiler no muestra esto. Solo nos muestra las funciones subsecuentes que se llaman para decir que no se vea la búsqueda. No me muestra qué iteraciones de bucle son más baratas frente a más caras. Tal vez solo la primera iteración es cara. Tal vez Mark solo necesita un montón de tiempo para inicializar y luego todas las llamadas subsecuentes son caras, ¿verdad? Así que no puedo asumir que todo allí es perfecto. Así que sí, conicly sugiere console time y esta es la función perfecta para este propósito. Así que cada vez que necesites ir al nivel de subfunción para averiguar cuánto tiempo lleva cada parte dentro de una función, No serías capaz de ver esto en el panel de performance por defecto. Y aquí es donde console time resulta realmente útil. Así que podrías haber oído hablar de console time. Console time es una función que básicamente se ve así. Llamas a console time, pasas cualquier etiqueta que quieras pasar en este caso, podemos llamarlo iteración de bucle, más el ID del nodo. Y eso comienza las mediciones para cualquier código que quieras medir eso comienza el temporizador. Luego usas, luego llamas a console time end con la misma etiqueta y eso detiene el temporizador. Y en el momento en que bloqueas console time ends, el navegador va a bloquear la duración de esta duración en la consola. Y podrías haber oído hablar de este caso de uso. Veamos cómo funciona esto. Voy a abrir los nodos, espera, voy a abrir los nodos y voy a inten

Uso de Console Time para la depuración del rendimiento

Short description:

La función de tiempo de consola en Chrome DevTools no solo es útil para registrar en la consola, sino que también registra en el panel de rendimiento. Esto te permite rastrear la duración de partes específicas de tu función e identificar las secciones más costosas. Al anotar tu código con tiempo de consola, puedes ver fácilmente la duración de diferentes partes de tu función sin tener que coincidir las llamadas de función con las líneas de código. Esto simplifica el proceso de depuración. En esta masterclass, cubrimos varios temas como Chrome DevTools, React Profiler, por qué renderizaste, coincidencia de números de hook con código, depuración de efectos y uso de tiempo de consola para depurar efectos. También discutimos los desafíos de imponer controles de rendimiento a nivel de CI de PR y recomendamos usar Lighthouse para verificar el rendimiento de carga.

Y esto es agradable. Esto es útil. Puedo hacer esto con solo bloquear la consola, ¿verdad? Pero una cosa genial sobre el tiempo de consola es que no solo se registra en la consola, también se registra en el panel de performance. Entonces, aquí, si ahora, si hago clic en grabar, si presiono una letra y dejo de grabar y miro mi, aquí está mi useEffect anónimo, aquí está mi función de guardar notas en el almacenamiento local que se divide en dos funciones porque por alguna razón, las herramientas de Chrome a veces lo hacen. Todavía es la misma función porque en el código, es la misma función. Y todavía solo puedo ver que las funciones marcadas aquí se están llamando, pero si subo, si subo y si miro el panel de tiempos que aparecería aquí, cada vez que empiezo a agregar cualquier tiempo, miraría el panel de tiempos y vería, mira, duración local para esta nota, duración local para esta nota, duración local para esta nota, duración local para esta nota, etcétera, etcétera, etcétera, etcétera, etcétera. Duración lógica para cada nota que he anotado de esta manera, incluyendo para la última muy barata. Y esto es súper, extremadamente conveniente para averiguar qué está pasando exactamente dentro de tu función y qué partes de la función son las más costosas. En este caso, todas las iteraciones de bucle cuestan más o menos lo mismo, pero solo hubo una que sería costosa. Serías capaz de rastrearlo de esta manera y averiguar qué está pasando realmente dentro de él.

Entonces Quinqui pregunta, lo siento, ¿cuál es el valor de esto? Ya podríamos ver cuánto valor estaba tomando Mark parse. Esto es realmente, sí, tal vez este no es un gran ejemplo. Tendría que pensar en un ejemplo más complicado, pero veamos. ¿Qué pasa si encontramos algún componente enorme, no sé, o useEffect, infusion charts ready, componente montado. Encuentro que es más útil en partes grandes de, lo siento, partes grandes, partes más complicadas de la confluencia, así que en este caso sabes que Mark parse es la función que hace el análisis. Y porque te lo dije, entonces sabes, sabes que esta función va a ser más o menos costosa para cada nodo, o es como el costo va a ser proporcional con el tamaño del nodo porque te lo dije. Pero cuando estás lidiando con algún código desconocido, y especialmente si ese código es grande, simplemente lo encuentro, definitivamente no es lo primero que uso bien cuando estoy depurando, pero cuando lo encuentro, como donde lo encuentro útil es cuando obtengo un montón de llamadas de función en aquí, y realmente no quiero simplemente tratar de separar cada una de estas funciones. Como tal vez obtendría como 40 llamadas de función aquí abajo, y todas ellas serían más o menos baratas. Y realmente no quiero tratar de mirarlas y tratar de manejarlas con este código. Resalto, esta función ocurre en esta línea, esta función ocurre en esta línea. A veces lo que haría, así que solo anotaría algunas partes de la función con tiempo de consola. Y escribiría las anotaciones de la manera en que entiendo la función en lugar de tener que volver atrás y primero y coincidir las llamadas de función con líneas e intentar averiguar qué sucede. Y entonces sería capaz de ver eso, como mira tal vez este si toma cinco milisegundos y este si toma siete milisegundos. Y realmente no necesito mirar qué funciones llama este si y este si si tengo mis anotaciones de consola. Simplemente hace que algunas partes del proceso de depuración parezcan más simples.

Entonces, si puedes lidiar con eso, es perfecto pero sé que, tiendo a usarlo a veces. Muy bien, así que esto fue lo último que quería mostrarte durante esta masterclass. Así que miramos varias cosas en esta masterclass. Miramos Chrome DevTools y Rack Profiler. Cómo perfilar las aplicaciones dentro. Miramos la aplicación Realworld. Aprendimos sobre por qué renderizaste. Aprendimos cómo coincidir los números de hook con el código. Aprendimos cómo debug efectos y por qué es importante seguir el gráfico de llama y mirar renderizado sincrónico versus efectos de diseño de commit y efectos pasivos de flash. Porque si solo vas directamente a Rack Profiler, entonces podrías perder la parte más costosa del renderizado que son en realidad los efectos. Y aprendimos cómo usar use ready para actualizar y tiempo de consola para debug por qué se actualizó un efecto y registra algunas partes de una función costosa algunas partes de un efecto costoso. Así que esto es todo por hoy. Siéntete libre de recordar o guardar este enlace al chat de Rack Profiler. Era accesible, se mantendría público. Déjame dejarlo en el chat una vez más. Y ahora es el momento para las preguntas y respuestas. ¿Tienen alguna pregunta sobre todo lo que pasamos hoy? ¿O tienen alguna pregunta sobre cualquier rendimiento de Rat en general? Tengo una pregunta. Sí, adelante. Entonces, ¿cuánto tiempo esperaste para que saliera la biblioteca? ¿Por qué renderizaste? Dijiste que esperaste algún tiempo. ¿Y ves que ese proyecto continúa? Porque obviamente esto es de código abierto, creo. ¿Ves como una tendencia que cada vez más personas van a contribuir a eso o tal vez a otra biblioteca que hace cosas similares? Lo siento, me perdí la primera parte de la pregunta. ¿Cuánto tiempo esperé para que saliera esta biblioteca? Sí. ¿Qué quieres decir con eso? ¿Cuándo salió? ¿Cuándo se lanzó al público, supongo?

Monitoreo y Optimización del Rendimiento de React

Short description:

Si quieres comprobar el rendimiento en tiempo de ejecución, puede ser más difícil de hacer. Hay herramientas y artículos disponibles que proporcionan información detallada sobre las pruebas y el monitoreo automatizado del rendimiento de React. Sin embargo, es importante destacar que reducir los problemas de rendimiento no es únicamente un desafío técnico. También implica aspectos culturales y la mentalidad del equipo. Simplemente introducir un proceso o herramientas para el monitoreo del rendimiento puede no ser efectivo si el equipo no prioriza el rendimiento. Es crucial fomentar una cultura donde se valore el rendimiento y contratar a individuos que se preocupen por él. Al tratar con bibliotecas de terceros, puede ser más desafiante optimizar el rendimiento. En algunos casos, enviar una solicitud de extracción a la biblioteca puede ser una opción, pero si la biblioteca no se mantiene activamente, parchear la biblioteca directamente en la base de código utilizando una herramienta como patch-package puede ser una solución. Sin embargo, entender el código de terceros y hacer cambios en él requiere un análisis cuidadoso. El compilador React Fiber puede ayudar a mejorar el rendimiento, pero no resolverá todos los problemas de rendimiento.

Si quieres comprobar el rendimiento en runtime, esto es más difícil, y el artículo que enviaron anteriormente, lo detalla en profundidad. Así que https://www.3perf.com, artículos y guías. Rendimiento automatizado de React. Lo detalla en profundidad, no voy a repetirme. Y también, hay algunas herramientas que no he usado. Monitoreo de rendimiento. Hay una herramienta llamada CallbackRezure, no la he usado. Es una especie de compañero de pruebas de rendimiento para CI. Esperemos que sea buena. Así que, esta es la respuesta corta. Estas son las herramientas. ¿Hay alguna otra? ¿Valores de NLP?, ¿verdad? No, oh sí, no. Así que, bueno, también hay este muy buen artículo de Netflix. Espera, no, lo siento. Bueno, esta es la respuesta corta, esta fue la respuesta corta. Estas son las herramientas, estas son las soluciones. La respuesta larga es que esto es complicado, y es complicado por dos razones. La técnica y la cultural. La técnica es que desde una perspectiva técnica, obtendrías mucho ruido. Lo he intentado en el pasado, siempre hay como un 10, 20% de ruido y a menos que la regresión sea realmente grande, tu Ponditorian no lo detectaría. Netflix ha encontrado algunas formas de reducir este ruido, específicamente parecen, aquí está la cantidad de ruido que realmente puedes obtener razonablemente. Miran, hacen dos cosas, hacen detección de anomalías y hacen, lo siento, realmente no recuerdo, sería mejor que lo revisaras, pero hablan mucho sobre los cambios que han hecho y es un increíble estudio de caso, así que el enfoque más ingenuo no funcionaría. Por favor, revisa el estudio de caso de Netflix para ver cómo redujeron el ruido. La segunda parte de la respuesta sobre la cosa cultural es que muy a menudo cuando trabajo con los equipos, veo algo que sucede, así que, espera, no, estamos en el sitio, así que Dan Lu cultura. Así que esto puede que no sea algo que puedas afectar como ingeniero, pero esto es algo, si planeas crecer más y volverte más senior, esto es algo que es realmente útil saber. Así que hay la diferencia entre la cultura y el proceso. Así que el proceso es cuando tomas algunas herramientas de rendimiento y configuras el monitoreo de rendimiento como un proceso y tú, no sé, obligas a la gente a asegurarse de que el rendimiento se mantenga bueno cada vez que introducen algunos cambios. Este es el proceso, introduces un nuevo proceso, la gente, si la gente sigue el proceso, todo está bien. La cultura es cuando contratas a la gente que realmente se preocupa por esto, realmente se preocupa por el rendimiento. Y también está el incentivo que es, sí, podrías requerir en la promoción que la gente haga algo más rápido, no sé. Pero estos tres enfoques diferentes, dan resultados diferentes y trabajando con mis clientes, trabajando en diferentes empresas, he encontrado que el enfoque del proceso generalmente no funciona bien a menos que la gente se preocupe por el rendimiento. Así que, no sé por qué estás preguntando sobre el monitoreo del rendimiento, tal vez todo el mundo en tu equipo se preocupa por el rendimiento y entonces eso está bien. Pero muy a menudo hablo con ingenieros que se preocupan por el rendimiento, pero el resto del equipo no se preocupa. Y ellos van como, hey, ¿cómo hago que el resto del equipo se preocupe? ¿Cómo hago esto? Tal vez configuro algún monitoreo de rendimiento, tal vez hago algo así. Y no puedes hacer eso como ingeniero. Se origina de la cultura, se origina de la contratación y se origina del liderazgo. Puedes hablar con el liderazgo, intentar convencerlos y puedes mostrarles esto para decir. Um. Así que. Sí. ¿Responde esto a la pregunta? Sí, genial, estupendo. Quinqui pregunta, en aplicaciones del mundo real, a menudo veo la camisa de llamas llena con código de la biblioteca de terceros HeeGG. Oh, y otros de mis favoritos. A menudo simplemente parece que está haciendo un montón de cosas pequeñas, nada realmente destaca. Sí. Así que esto es complicado, no tengo un buen marco para esto, una buena solución para esto. La forma en que lo hago, la forma en que abordo esto es, normalmente solo trato de mirar el panel de rendimiento, y reviso el panel de rendimiento, e intento notar los puntos cuando una gran función se divide en un montón de funciones más pequeñas. Básicamente cuando el árbol se ramifica hacia abajo. Porque cuando eso sucede, bueno, eso sucede eso significa, tal vez tenemos un bucle que llama a la misma función una y otra vez en una fila. O tal vez eso significa que la función hace muchas cosas y llama a un montón de otras funciones. Pero de todos modos, eso atrae mi atención porque normalmente cuando miro eso, es un buen punto para empezar a optimizar. Y esto funciona bien con tu código. Con terceros SysWay Tree Card, cuando trabajas con algo como un ggrid, realmente no puedes, hay mucho menos que podrías hacer. Así que todavía entro en terceros e intento optimizarlos. Y entonces lo que hago es, realmente no creo en las solicitudes de extracción. La buena acción es intentar y enviar la solicitud de extracción a la biblioteca para que se arregle. En más de la mitad de los casos, la biblioteca no se mantiene tal vez se toman un año para fusionar las solicitudes de extracción o cosas así. Pero si el problema radica en un ggrid o en alguna otra biblioteca de terceros, lo que he hecho a veces es simplemente parchear la biblioteca directamente en NodeModules. Hay un paquete en npm llamado patch package. Y lo que te permite hacer es te permite hacer algunos cambios en NodeModules y luego simplemente guardar estos cambios en tu base de código y volver a aplicar los cambios en cada instalación subsiguiente. Así que déjame soltar eso. Y lo hemos hecho realmente como, no sé si quieres un caso si quieres un caso de uso. Yadda yadda yadda casual, casual, casual. Así que lo hemos hecho realment

Conclusión de la Masterclass de Rendimiento de React

Short description:

Arreglar las cosas de código estándar es útil, pero hay otros problemas de rendimiento que abordar manualmente. Gracias por asistir a la masterclass. Recibirás una grabación de la sesión. Sígueme en Twitter para más consejos de rendimiento. ¡Espero verte de nuevo!

Creo que solucionará la parte más molesta de ellos, que es todo el código estándar que tienes que hacer. Pero, desafortunadamente, hay muchas más cosas que podrían suceder, como acabamos de ver, acabamos de ver uno de estos ejemplos, vimos un use effect que se ejecuta cada vez y que llama a una función muy costosa. Y realmente no puedes hacer nada al respecto, automáticamente, necesitas mirarlo realmente y averiguar cómo optimizar.

Muchas gracias por venir a la masterclass, tendrás una grabación, sí, esto es algo de lo que hablar con la gente de GitNation. Entonces, creo que recibirás la grabación en el portal. Así que, muchas gracias por venir a esta masterclass, fue un enorme placer trabajar contigo.

Un poco de autopromoción, estoy en Twitter, que solía ser, que es xnow. Publico trivialidades de performance, así que siéntete libre de seguirme para obtener tips y trucos de performance directos. Y muchas gracias por venir. Y espero verte en algún otro momento, quizás en una conferencia. Bien, que tengas un gran resto del día, adiós.

Watch more workshops on topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
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 🤐)
JSNation 2023JSNation 2023
170 min
Building WebApps That Light Up the Internet with QwikCity
Featured WorkshopFree
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.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
WorkshopFree
- 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
Vue.js London 2023Vue.js London 2023
49 min
Maximize App Performance by Optimizing Web Fonts
WorkshopFree
You've just landed on a web page and you try to click a certain element, but just before you do, an ad loads on top of it and you end up clicking that thing instead.
That…that’s a layout shift. Everyone, developers and users alike, know that layout shifts are bad. And the later they happen, the more disruptive they are to users. In this workshop we're going to look into how web fonts cause layout shifts and explore a few strategies of loading web fonts without causing big layout shifts.
Table of Contents:What’s CLS and how it’s calculated?How fonts can cause CLS?Font loading strategies for minimizing CLSRecap and conclusion
React Summit 2022React Summit 2022
50 min
High-performance Next.js
Workshop
Next.js is a compelling framework that makes many tasks effortless by providing many out-of-the-box solutions. But as soon as our app needs to scale, it is essential to maintain high performance without compromising maintenance and server costs. In this workshop, we will see how to analyze Next.js performances, resources usage, how to scale it, and how to make the right decisions while writing the application architecture.
JSNation 2023JSNation 2023
44 min
Solve 100% Of Your Errors: How to Root Cause Issues Faster With Session Replay
WorkshopFree
You know that annoying bug? The one that doesn’t show up locally? And no matter how many times you try to recreate the environment you can’t reproduce it? You’ve gone through the breadcrumbs, read through the stack trace, and are now playing detective to piece together support tickets to make sure it’s real.
Join Sentry developer Ryan Albrecht in this talk to learn how developers can use Session Replay - a tool that provides video-like reproductions of user interactions - to identify, reproduce, and resolve errors and performance issues faster (without rolling your head on your keyboard).

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

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
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
JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Few developers enjoy debugging, and debugging can be complex for modern web apps because of the multiple frameworks, languages, and libraries used. But, developer tools have come a long way in making the process easier. In this talk, Jecelyn will dig into the modern state of debugging, improvements in DevTools, and how you can use them to reliably debug your apps.
React Summit 2023React Summit 2023
32 min
Speeding Up Your React App With Less JavaScript
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 Summit 2023React Summit 2023
23 min
React Concurrency, Explained
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
JSNation 2022JSNation 2022
21 min
The Future of Performance Tooling
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.
React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.