Masterclass de Depuración de Rendimiento de React

Rate this content
Bookmark
Github

Los primeros intentos de Ivan en la depuración de rendimiento fueron caóticos. Vería una interacción lenta, intentaría una optimización aleatoria, vería que no ayudaba, y seguiría intentando 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. Haría una grabación en Chrome DevTools o React Profiler, la examinaría, intentaría hacer clic en cosas aleatorias, y luego la cerraría 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 a 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, estaremos cubriendo el rendimiento de la interacción, no la velocidad de carga, por lo que no escucharás una palabra sobre Lighthouse 🤐)

Ivan Akulov
Ivan Akulov
170 min
19 Jun, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Esta Masterclass sobre Rendimiento de React cubre varias técnicas y herramientas para analizar y optimizar el rendimiento de la aplicación. Incluye el uso de los paneles de Rendimiento y Profiler de Chrome DevTools, el análisis de la actividad de la CPU y las llamadas a funciones, la identificación de renders y componentes costosos, la depuración con 'why did you render', y la optimización del código y efectos de React. La masterclass también discute el uso de la API ConsoleTime para el perfilado, la optimización del gestor de estado, y el análisis del rendimiento de la memoria. En general, proporciona valiosos conocimientos para mejorar el rendimiento de las aplicaciones de React.

Available in English

1. Introducción a la Masterclass de Rendimiento de React

Short description:

Bienvenidos a la Masterclass de Rendimiento de React. Hoy hablaremos sobre cómo abordar los problemas de rendimiento de React y analizar una aplicación lenta. Utilizaremos el panel de rendimiento de Chrome DevTools para grabar y analizar el rendimiento de la aplicación. Comenzaremos mirando la fila de CPU para identificar dónde la aplicación es lenta. Luego, ampliaremos una grabación para analizar el panel principal durante los picos de CPU.

♪♪ Bienvenidos a la React Performance Masterclass para la Cumbre de React. Estoy muy contento de conocerlos a todos y de haber hablado ya con algunos de ustedes. Soy Ivan, un experto en DevOps de Google. Soy un ingeniero de rendimiento web. He estado trabajando en rendimiento durante cinco años en este punto. He trabajado con empresas como Google, CNBC, Framer, etc. Y hoy vamos a hablar sobre las formas de abordar los problemas de rendimiento de react cuando tu aplicación es lenta y necesitas averiguar por qué. Pero no estás realmente seguro de cuáles son los próximos pasos a seguir. Que era básicamente yo al principio de mi carrera.

Y para empezar... Oh sí. Cosas de trabajo. Entonces, la masterclass dura tres horas, ¿verdad? Tendremos descansos de 10 minutos cada hora. Tenemos tiempo para preguntas y respuestas al final. Si tienes alguna pregunta en el proceso, no dudes en... En realidad, lo siento, creo que esta reunión es un poco grande para que Ani pregunte. Así que sí, no viste eso. Si tienes alguna pregunta, no dudes en hacerla en los chats o guárdala para las preguntas y respuestas al final. Y también, en caso de que seas la persona a la que le gusta tomar notas, hay un enlace, bit.ly dash Ares para notas, que, si vas a ese enlace, verás este documento llamado React Performance Masterclass, Notas Colaborativas. Y aquí encontrarás el enlace a este documento, al rep de Google o al chat de Discord, donde dejaré los enlaces después de esta masterclass. Y también, si tomas alguna nota o si tienes alguna pregunta que quieras hacer más tarde pero no quieres olvidar, no dudes en guardarlas en las notas aquí para que todos puedan colaborar en las notas y todos se beneficien.

Y para empezar, vamos a mirar una aplicación lenta de inmediato. Así que si abres este repositorio y si clonas este repositorio, que ya he clonado, y abres el directorio de notas, e instalas las dependencias y luego ejecutas yarnstart, obtendrás esta básica nota tomada. Tú, como, si asististe... Si asististe a la charla que estaba dando sobre el tiempo de rect, es sobre la concurrency de rect. Podrías haber visto esto, que no es una coincidencia, pero no vamos a hablar sobre la concurrency de rect hoy, vamos a hablar sobre otros problemas. Y esta aplicación tiene un desafío de rendimiento. Específicamente, si creas unos pocos... Oops, perdón, cambia entre esto. Si creas unas pocas cientos de nodos, como 500, 600, 700, y luego abres cualquiera de estos nodos, y luego intentas escribir en el editor, la aplicación se sentirá bastante lenta, bastante lenta. Así que aquí estoy escribiendo en el editor de la aplicación, y la aplicación se siente lenta. Ahora realmente no puedes ver eso, ¿verdad, porque es mi portátil, soy yo escribiendo, soy yo sintiendo esto. Realmente no puedes notar que es lento. Así que una cosa que voy a hacer para que veas cuando la aplicación es lenta es que voy a ir a DevTools, Más Herramientas, Renderizado, y voy a hacer clic en la casilla de Estadísticas de Renderizado de Cuadros. Así que cuando hago clic en la casilla de Estadísticas de Renderizado de Cuadros, obtengo en la esquina superior izquierda esta cosa, que básicamente me muestra cuando el Hilo Principal está ocupado o inactivo. Así que ahora, si hago algo rápido, como desplazar esta lista, puedo ver que mi tasa de cuadros por segundo se mantiene alta, y aparecen algunas líneas rojas y amarillas, lo que significa que el Hilo Principal estuvo ocupado con algún trabajo durante un período de tiempo muy corto. Pero si intento escribir en el editor, podrías ver cómo la tasa de cuadros por segundo cae inmediatamente con cada pulsación de tecla. Y puedes ver cómo el Hilo Principal comienza a llenarse de rojos. Lo que básicamente significa que el Hilo Principal está bloqueado. Así que incluso si sólo escribo una sola letra, puedes ver el Hilo Principal bloqueado durante algún período de tiempo prolongado. O si simplemente escribo varias letras a la vez, acabo de escribir un montón de letras y la aplicación estaba tan ocupada, que ni siquiera actualizó las tasas de cuadros. ¿Gráfico, es esto un gráfico? ¿Quizás esto es un gráfico? Pero de todos modos, tenemos un problema de rendimiento. Estoy escribiendo en el editor y la aplicación es lenta. Ahora, cada vez que tengo un problema de rendimiento, lo primero que siempre hago es ir a ChromDevTools, abro el panel de Performance, e intento grabar lo que está pasando en la aplicación durante este problema de rendimiento usando el panel de Performance. Así que lo que voy a hacer ahora es abrir el panel de Performance, que ya tengo abierto, voy a hacer clic en Grabar, voy a escribir en el editor, pero no un montón de letras a la vez, como acabo de hacer. Porque eso va a disparar un montón de JavaScript, supuestamente o lo que sea, lo que sea que esté ralentizando la aplicación. Pero sólo una letra y luego esperar un poco, otra letra y luego esperar un poco de nuevo, y otra letra, y luego detener la grabación. Y una vez que hago esto, obtendría esta grabación de rendimiento que me mostrará todo lo que ha estado pasando en la aplicación durante la grabación, mientras estaba escribiendo en estos botones del teclado. Así que si ves esto por primera vez, esto podría ser un poco abrumador, porque hay muchas cosas pasando aquí. Pero las únicas dos áreas reales en las que necesitamos centrarnos son la fila de CPU, que muestra cuando la aplicación, cuando el hilo principal estaba ocupado, y el panel principal, que muestra qué estaba pasando exactamente en la aplicación cuando la aplicación estaba ocupada. Así que ahora lo primero que voy a mirar, acabo de grabar, acabo de hacer una grabación de rendimiento, ¿verdad? Así que lo primero que voy a mirar para tratar de averiguar qué está pasando en la aplicación es que voy a mirar la fila de CPU, y voy a tratar de averiguar qué exactamente, o averiguar dónde exactamente la aplicación es lenta. Y puedo ver, como, esto es bastante fácil de ver, ¿verdad? Cuando la fila de CPU está vacía, eso significa que la aplicación estaba inactiva. Cuando la fila de CPU está llena de algún color, como el amarillo en este caso, para JavaScript, esto significa que la CPU estaba ocupada ejecutando algún código. Así que en este caso, veo tres picos de actividad de la CPU, que, supongo, corresponde a mí escribiendo en el editor. Así que lo que voy a hacer a continuación es, voy a ampliar una de las grabaciones y cambiar al panel principal e intentar averiguar qué está pasando exactamente en el panel principal durante el pico de actividad de la CPU. Y así que echemos un vistazo. Así que tenemos un pico de actividad de la CPU. El pico de actividad de la CPU tomó 215 milisegundos. En el pico de actividad de la CPU, tenemos dos rectángulos que indican lo que ha estado pasando en el nivel más alto. Así que tuvimos una tarea, una sola tarea, que significa un solo período de tiempo ininterrumpido cuando el navegador estaba procesando algo. Esta tarea tomó 200, lo siento, 215 milisegundos. Y durante esta tarea, obtenemos dos eventos. Uno, el evento de tecla hacia abajo, que tomó sólo tres milisegundos para manejar. Y otro, el evento de presión de tecla que tomó 212 milisegundos para manejar. Así que el primero probablemente no es muy importante porque es, así que en primer lugar, mira hasta ahora. Hasta ahora todo bien, ¿verdad? Esto coincide con lo que obtengo en la aplicación. Escribí en el editor, obtuvimos el evento de presión de tecla, el evento de tecla hacia abajo.

2. Análisis del Evento de Pulsación de Tecla y Llamadas a Funciones

Short description:

El evento de pulsación de tecla es el más costoso. Desencadena el evento de entrada de texto, que a su vez desencadena el evento de entrada. Estos eventos conducen a múltiples llamadas a funciones, principalmente de desarrollo de Ragdoll y del núcleo de React.

Entonces, el evento de pulsación de tecla es barato. Voy a ignorarlo por ahora, pero me voy a centrar en el evento de pulsación de tecla, que es, lo siento, el evento de tecla hacia abajo es barato. Me voy a centrar en el evento de pulsación de tecla, que es el más costoso. Así que se disparó el evento de pulsación de tecla. El evento de pulsación de tecla a su vez desencadenó el evento de entrada de texto. El evento de entrada de texto a su vez desencadenó el evento de entrada. El evento de entrada desencadenó alguna llamada a función, que parece ser en su mayoría esta función textAreaInputPol, que es algo, no voy a profundizar en eso ahora. Solo estoy echando un vistazo de alto nivel. Y luego el rectángulo runMicroDosks, que tomó 209 milisegundos, así que todavía la mayor parte del tiempo. Así que runMicroTasks desencadenó otra llamada a función, que en este caso parece venir del desarrollo de Ragdoll. Y esa llamada a función desencadenó otra llamada a función, y esa llamada a función desencadenó otra llamada a función, y luego esa llamada a función desencadenó otra llamada a función. Y lo que veo aquí es un montón de eventos de entrada de texto llamadas a funciones que vienen del desarrollo de Ragdoll, que vienen del núcleo de React.

3. Análisis de Funciones y Uso del Rack Profiler

Short description:

Al analizar la actividad de la CPU y las funciones, el color de las funciones indica que provienen de la misma fuente. La aplicación es lenta al escribir en el editor, lo que desencadena una tarea de JavaScript y una cadena de eventos que ejecutan mucho código de rack. Ver mucho código de rack en la grabación indica la necesidad de cambiar al Rack Profiler. La pestaña Profiler proporciona una visión general de lo que está sucediendo en la aplicación. Grabar con la pestaña Profiler revela la lista de renders y los componentes renderizados durante cada render. Las preguntas del chat aclaran la interacción y la capacidad de grabar múltiples iframes con el panel de rendimiento.

Y así, si miro a través de estos picos de actividad de la CPU, si miro a través de todas estas funciones, y por cierto, en realidad no necesito mirar todas estas funciones, porque si miras estas funciones, notarás que tienen este color rosa, rosado, no sé, color rosa claro. Así que este color no significa nada en particular, es aleatorio. Pero lo que sé cuando veo funciones con el mismo color, como todas estas funciones en este caso, lo que sé cuando veo funciones todas coloreadas con el mismo color, sé que estas funciones están todas llegando desde la misma fuente.

Entonces, lo que hace Chrome DevTools es, siempre que tenemos funciones que provienen de diferentes archivos o de diferentes fuentes, intentan colorear estas funciones con el mismo color si provienen del mismo archivo. Así que en este caso, ni siquiera necesito revisar todas estas funciones para confirmar que provienen del desarrollo de Rackdown. Solo puedo hacer clic en esta, hacer clic en esta, hacer clic en esta, confirmar que todas provienen del desarrollo de Rackdown, y luego asumir que probablemente el resto de ellas también provienen del mismo lugar. Muy bien.

Entonces, esto es lo que hemos aprendido hasta ahora. Tenemos una aplicación lenta. La aplicación se retrasa cuando estoy escribiendo en el editor. Cuando estoy escribiendo en el editor, cuando escribo una sola letra en el editor, obtengo una sola tarea de JavaScript que tarda alrededor de 200 milisegundos. Esa tarea de JavaScript desencadena un evento de pulsación de tecla y el evento de pulsación de tecla a su vez, a través de un montón de otros eventos, desencadena un montón de código de rack. Ahora, en este punto, cuando veo mucho código de rack, no necesito saber qué hace este código. No necesito estar familiarizado con él. No necesito conocer los detalles internos de rack. Lo que sé cuando veo mucho código de rack en la grabación, cuando veo que el código de rack ocupa la mayor parte de la grabación, es que sé que puedo cambiar a una herramienta diferente que me dará una mejor visión general de lo que está sucediendo en la aplicación, y esta herramienta es el Rack Profiler.

Entonces, Rack Profiler es una herramienta que viene de la extensión Rack DevTools. Entonces, si simplemente buscas en Google las herramientas de desarrollo de Rack e instalas esto y luego recargas las DevTools y recargas la página, obtendrás este trabajo, estoy bastante seguro de que la mayoría de ustedes ya lo tienen instalado. Pero, lo que voy a hacer es, dado que la mayoría del código aquí, la mayoría del código aquí proviene de Rack, voy a cambiar a la pestaña Profiler, y voy a volver a grabar la misma interacción que acabo de hacer usando la pestaña Profiler, la pestaña Rack Profiler. Entonces, esto es lo que voy a hacer. Voy a hacer clic en Grabar, que es no va a funcionar por alguna razón. Ahora funciona. Voy a hacer clic en Grabar, voy a volver a hacer la interacción. Uno, dos, tres, y voy a detener la grabación. Y luego, una vez que el navegador deje de procesar la grabación, obtendré un montón de nuevos datos adicionales sobre lo que ha estado sucediendo en la aplicación mientras React estaba funcionando. Y entonces veamos lo que tenemos aquí. Tenemos, en primer lugar, tenemos la lista de todos los renders que ocurrieron en la aplicación. Así que hice clic en el botón del teclado tres veces y eso aparentemente causó tres renders. Puedo ver tres renders en esta fila uno, dos, tres. Todos estos renders parecen haber tomado aproximadamente la misma cantidad de tiempo. Así que dos, tres, tres, uno, nueve, nueve, dos, uno. Bueno, probablemente son bastante similares. Y luego en cada render, si hago clic en cualquiera de los renders, vería todos los componentes que se renderizaron en la aplicación durante ese render exacto.

Y veo algunas preguntas en el chat. Escribámoslo aquí. Tittered dice que no escribiste en el cuadro de búsqueda, o el profiler no grabó lo mismo. Así que en realidad, para esta masterclass, no estoy escribiendo realmente en el cuadro de búsqueda. Así que cuando estaba haciendo la charla, estaba escribiendo en el cuadro de búsqueda. Aquí estoy escribiendo en el editor. Así que podría ser fácil confundirlo porque es la misma aplicación, ¿verdad? Pero sí, esa fue la misma interacción. Estaba escribiendo en el editor. Es lo mismo. Lo siento. Lo siento, espero haberlo pronunciado bien. Sarayo pregunta, ¿hay alguna manera de hacer eso cuando la aplicación no está en un iframe? Así que cuando tienes varios iframes, creo que tienes una forma de exponer las herramientas de desarrollo de React. Entonces, oh sí, lo siento. Podrías responder a esto en relación con el panel de rendimiento o en relación con el panel de rendimiento. Así que con el panel de rendimiento, el panel de rendimiento graba todos los iframes al mismo tiempo. Así que si vas a cualquier sitio web que tenga un iframe, como tal vez puedo ir a KotPen.io y como, veamos lo que esto era. No recuerdo lo que era esto. ¿Esta cosa es un iframe, verdad? No, no quiero ir al Pro. Y como, si grabo lo que está pasando con el panel de rendimiento, como probablemente necesito algo de JavaScript, ¿verdad? Hagamos, espera. No. Vale. Voy a escribir eso manualmente. Hagamos esto setTimeout. Eso se ejecuta cada segundo y luego, bloquea los hilos principales durante cien milisegundos. Cuenta ahora, rendimiento ahora. Mientras ahora, más cientos es menos. Espera. Ahora más 100 es más que el rendimiento. Ahora. Vale. Supuestamente deberían mirar el hilo principal durante cien milisegundos. Ahora si setInterval. Así que ahora si grabo lo que está pasando, así que ahora si grabo lo que está pasando con el panel de rendimiento, obtendría, en realidad obtendría un panel adicional además del panel principal. Así que obtendría el panel principal, que muestra todo lo que sucede en el iframe principal. Y obtendría un montón de marcos que muestran lo que ha estado sucediendo en los iframes. Y te muestran prácticamente lo mismo. No necesitas hacer nada específico para habilitar eso.

4. Análisis del rendimiento de la aplicación y del código de React

Short description:

Para depurar la grabación y hacerla más legible, alejarse y examinar los componentes reveló que el cuello de botella eran los componentes NotButton. Eliminar 700 NotButtons y crear 100 mejoró el rendimiento de la aplicación y hizo que la grabación fuera más legible. Sin embargo, la grabación con el profiler no funcionó correctamente debido a posibles errores del navegador o de las DevTools. El perfilado del rendimiento con el profiler o el panel de rendimiento puede ser desafiante debido a estos errores y decisiones de diseño. A pesar de estos desafíos, hemos obtenido información valiosa sobre el rendimiento de la aplicación y el papel del código de React.

Funciona directamente. Con el panel de rendimiento, es bastante fácil. Con el profiler, es más difícil. Creo que necesitas hacer algunas cosas para exponer el iframe de React o las herramientas de React. Sí, necesitas, oh sí. Básicamente, necesitas hacer esto. Espero que este código no esté desactualizado. Oh no, es 2022. Probablemente no lo esté. Pero sí, si agregas esto a tu iframe, tus herramientas de desarrollo también deberían funcionar bien. Incluso te permitirían elegir qué iframe elegir para perfilar. Así que, sí. Ahora volvamos al profiler.

Entonces, si grabo todo lo que está sucediendo, si grabo la interacción que estoy teniendo, no sé por qué no está funcionando. Si grabo lo que está sucediendo en la aplicación con el profiler, vería cada componente que se renderiza durante mi interacción. Vería todos los renders que ocurrieron durante mi interacción. Y vería cada componente renderizado, cada componente que se vuelve a renderizar durante cada render. Así que en este caso, estoy escribiendo en el editor. Uno, dos, tres, obtengo tres renders. Y durante cada uno de los renders, parece ser más o menos los mismos componentes que se renderizan cada vez, ¿verdad? Tengo el componente de la aplicación renderizando. Tengo el componente DarkModeProvider renderizando. Tengo el componente ContextProvider renderizando. Luego tengo los componentes de la lista de nodos renderizando. Y luego dentro de la lista de nodos, obtengo algunos filtros y luego algunos botones de nodo renderizando. Así que en este punto, podría confundirme un poco porque lo que veo aquí es que veo los componentes de la lista de nodos tomando uno, así que, espera, en realidad, ¿me estoy adelantando un poco? Tal vez, no, no lo sé, pero en este punto, podría confundirme un poco porque lo que veo debajo de la lista de nodos, veo algunos componentes que se renderizan, como un montón de botones de nodo, pero también veo un montón de espacio en blanco. Y así, si he trabajado con el panel de componentes antes, sé que el espacio en blanco generalmente significa que el navegador no estaba haciendo nada en este período de tiempo. Como aquí está el espacio en blanco, eso significa que el navegador está inactivo. Pero en el panel de profiler, el espacio en blanco no tiene el mismo significado. El profiler de Rack se comporta de manera diferente. Lo que sucede aquí es que si tienes muchos componentes, si renderizas una cantidad realmente grande de componentes, y la cantidad de componentes no puede caber en lo que sea que le hayamos dado, Rack simplemente seguirá renderizando estos componentes. Entonces, lo que sucede aquí no es que el navegador esté inactivo y no esté haciendo nada. Lo que sucede aquí es que tenemos tantos componentes que el profiler de Rack simplemente no puede mostrarlos en este espacio que tiene. Como todos estos componentes terminan siendo más estrechos que un píxel. Entonces, lo que hace Rack es que simplemente no los renderiza en absoluto. Así que esto es un poco confuso. Esto podría ser un poco confuso, pero ten esto en cuenta. Esto podría suceder si tienes listas enormes. Y así, lo que hago cuando veo este espacio enorme, como un montón de espacio vacío, lo que suelo hacer para confirmar si ese es el caso, simplemente hago zoom hasta que Rack renderice más componentes, y realmente puedo confirmar que, okay, ¿esto es, es esto solo como, es esto algún error extraño sobre el espacio en blanco? ¿O hay realmente un montón de componentes que no se pueden renderizar? Así que, no se pueden ajustar en su lugar. Así que aquí ves, hice zoom y Rack renderizó más componentes. Así que sí, esto es una confirmación. Esta fue mi forma rápida de verificar que, okay, este espacio en blanco no es el navegador estando inactivo, este espacio en blanco es simplemente que Rack no puede ajustar los componentes en la grabación. Pero esto es realmente molesto para depurar, ¿verdad? Tengo que ver los componentes. Así que lo que voy a hacer entonces, lo que voy a hacer ahora para que sea más fácil depurar, es alejarme y tratar de ver, ups, diferentes app. Voy a tratar de ver los componentes concretos que tengo aquí. Y, okay, todos estos componentes parecen ser solo NotButtons, componentes de botones de nodo, ¿verdad? Así que básicamente voy a alejarme y voy a ver todo lo que está sucediendo aquí. Y voy a tratar de averiguar qué exactamente está sucediendo en la aplicación y si puedo hacer que esta grabación sea un poco más fácil de entender. Así que lo que tenemos aquí es un re-renderizado. Durante este re-renderizado, se renderizó el componente de la aplicación, el componente de la aplicación hizo que se renderizara DarkModeProvider, DarkModeProvider hizo que se renderizara ContextProvider y ContextProvider hizo que se renderizara NotList y luego NotList se renderizó y también se renderizó los filtros y luego se renderizaron un montón de componentes NotButton, que si los paso por encima, puedo ver qué componentes corresponden en la aplicación. Así que puedo pasar el mouse por encima de esto y veo que estos componentes se resaltan. Así que esto es bastante bueno. Y así, si muevo el mouse por esta grabación alejada, que es muy molesta, sí, a veces tienes que hacer eso. Vería que todos estos componentes, la mayoría de estos componentes parecen ser solo NotButtons, como esto es como el 90% de la grabación en este punto, ¿verdad? Así que tal vez lo que puedo hacer para que la grabación sea más legible es por qué no elimino todas las notas y luego creo solo 100 notas en lugar de 700 y luego trato de grabar lo que está sucediendo en la aplicación con solo 100 notas en lugar de 700. Entonces, la aplicación probablemente se volvería más rápida si el principal cuello de botella aquí son los componentes NotButton, lo cual parece ser porque hay tantos de estos componentes NotButton simplemente renderizándose y ocupando como el 90% de todo el espacio de la grabación. Probablemente sean los componentes NotButton los que están en el cuello de botella. Así que si elimino todos mis 700 NotButtons y creo solo 100, la aplicación se volverá más rápida, pero eso también podría hacer que la grabación sea más legible. Así que vamos a intentarlo. Así que eliminé todas las notas. Creé 100 notas. Ahora, si escribo en el editor y habilito las estadísticas de renderizado de frames. Si escribo en el editor, todavía puedo ver que mis hilos principales se ocupan, aunque por un período de tiempo más corto. Y si voy al panel de rendimiento y hago clic en grabar, todavía puedo ver las tareas de JavaScript a través del keeper mientras gana y luego un montón de código de React se ejecuta debajo. Pero ahora, si voy al profiler y grabo la misma interacción con el profiler, que nuevamente no funciona. No estoy seguro si esto es un problema de DevTools, ¿es un problema de mi navegador? Si grabo la misma interacción, esta vez en realidad no obtendría espacio en blanco porque tenemos muchos menos componentes y todos ellos encajan. Así que esto fue tal vez una digresión un poco más larga sobre cómo resolver esto, pero la razón por la que lo muestro es muy intencional, cuando estás perfilando el rendimiento con un profiler o perfilando el rendimiento con un panel de rendimiento o cuando estoy perfilando el rendimiento con un panel de rendimiento, cuando estoy perfilando el rendimiento con un profiler, a menudo me quedo atascado con errores del navegador o errores de las herramientas de desarrollo y son muy molestos de solucionar y también son muy confusos si no sé qué está sucediendo exactamente. Así que esto que acabo de mostrar, es uno de los errores del profiler, tal vez decisiones de diseño que para mí son muy confusas. Así que la razón por la que lo muestro aquí es porque podrías encontrarte con esto y si fuera yo haciendo esto por primera vez, definitivamente me confundiría. Muy bien, esto es lo que hemos aprendido hasta ahora. Hicimos una grabación de rendimiento de lo que está sucediendo en la aplicación cuando tenemos una interacción lenta. Vimos que la mayor parte del código, la mayor parte de lo que está sucediendo en la aplicación durante la interacción lenta es el código de React. Pasamos por el panel de profiler.

QnA

Análisis del rendimiento de la aplicación y la renderización de componentes

Short description:

Grabamos la interacción lenta con las Chrome DevTools y aprendimos que la mayor parte de la actividad se debía al código directo. Utilizamos el Profiler de React para analizar los componentes que se volvían a renderizar durante la interacción. El componente de la lista de nodos con sus hijos tardó más tiempo en renderizarse. Para depurar aún más el problema de rendimiento, habilitamos la opción 'grabar por qué se renderiza cada componente durante el perfilado' en la configuración del Profiler.

Grabamos lo que está sucediendo en la aplicación con el panel del profiler y aprendimos qué exactamente está sucediendo cuando se ejecuta el código de React. Aprendimos todos los componentes que se están renderizando cuando se ejecuta el código de React. Entonces, mi siguiente pregunta ahora es, ¿vale, pero por qué exactamente se está renderizando todo esto? ¿Qué puedo hacer para solucionarlo? Pero antes de llegar a eso, ¿tienen alguna pregunta sobre lo que hemos visto hasta ahora? Este es el momento adecuado para desactivar el silencio y preguntar si quieren desactivar el silencio y preguntar. ¿Tienen alguna pregunta sobre el panel de rendimiento o el panel del profiler?

¿Una pregunta? Sí, adelante. Mi nombre es Gabriel, llegué un poco tarde y vi todas tus cosas, así que solo quería preguntar si podrías, si más adelante podrías hacer una revisión de lo que acabas de hacer hasta ahora, necesitas tocarlo en una hora. Si vas a tocar, lo siento, ¿qué? No lo entendí. Tuve problemas para conectarme, así que solo lo que has hecho hasta ahora, solo una pequeña revisión o algo así, ya sea ahora o más tarde. Oh sí. No creo que volvamos a repasar todo desde el principio, pero tendremos más ejemplos en la masterclass. Así que más aplicaciones lentas. Y por cierto, esto es muy... ¿Hay alguien que realmente esté interesado? ¿Podrían escribir en el chat, podrían enviar un más en el chat si ya saben el 95% de lo que hemos visto hasta ahora y un menos si saben menos, así que más si ya saben el 95% de lo que... Veamos un montón de más, un montón de menos. Bien, gracias. Sí, lo que está sucediendo ahora es que tengo este ejemplo muy, muy aislado, ¿verdad? No es un problema único. Así que este no es el único ejemplo que veremos hoy. Después de esto, una vez que hayamos terminado con esto, echaremos un vistazo a una aplicación del mundo real, una aplicación de código abierto muy compleja de React, y veremos cómo podría ser el perfilado del rendimiento. Veremos cómo abordo el perfilado del rendimiento de estas aplicaciones. Y bueno, con suerte, si saben todo lo que hemos visto hasta ahora, con suerte podrán aprender algo nuevo en esa parte. Así que tengo una pregunta más. Perdón. Entonces, en caso de que vea espacios en blanco, y no es por un problema de visualización, ¿mi interpretación sería que es porque el padre está ocupado? Entonces, en tu ejemplo, sería que la lista de nodos está haciendo demasiado trabajo. Si no veo nada debajo, pero te aparece en el profiler de rendimiento. ¿Es correcto? Oh sí, creo que sí. Creo que la forma en que funcionan las DevTools de React, y por cierto, ves, en las DevTools ves dos números, ¿verdad? Como la lista de nodos 0.7ms de 45ms. Entonces, el primer número significa, como cuánto tiempo tardó en renderizar estos componentes específicamente. El segundo número significa cuánto tiempo tardó en renderizar estos componentes con todos sus hijos. Y renderizar aquí significa literalmente llamar a este componente. Si tienes un componente funcional, React literalmente llama a este componente para renderizarlo. Entonces, si tienes un componente funcional, eso es si tienes un componente funcional que está haciendo demasiado trabajo. Como la lista de nodos, por ejemplo, tiene códigos que tardan 10ms. Lo que harían las DevTools de React es que, al principio, creo que eliminarían el espacio que es proporcional a estos 10ms. Así que obtienes un montón de espacio libre al principio y luego obtendrías todos los componentes que realmente se están renderizando. Pero el espacio libre al principio no debería haber más espacio libre según mi experiencia. Muy bien, gracias. Ramiro pregunta, ¿hay otras opciones para herramientas de perfilado? Sí y no. En realidad, tengo esta diapositiva en mis diapositivas con todas las herramientas de depuración que uso durante el perfilado. Mis dos herramientas principales son el panel de rendimiento, el profiler directo y los profilers directos, desafortunadamente, a veces tienen errores y tengo que lidiar con eso, pero también veremos otras herramientas de depuración como estas dos y algunas otras a lo largo de la masterclass. No reemplazan al profiler correcto, pero complementan y ayudan a facilitar el perfilado. Jory pregunta, intenté el panel de rendimiento en una de las aplicaciones de mi empresa, pero veo muchas de estas extrañas abreviaturas de dos letras como Z I, X D, T J, C S, etc. ¿Qué significan? Creo que lo que sucede en ese caso es simplemente porque está minificado. Como si fueras a Reddit.com, por ejemplo, y trataras de... Oh sí, tienes razón. Tengo... Oh, espera Airbnb. Intentemos Airbnb, es el sitio también clasificado. Si intentas grabar lo que está sucediendo aquí, también verás todas estas cosas. R S, F S, lo que sea. Son solo nombres minificados de funciones. Ramiro pregunta, ¿se grabará la masterclass? Sí. La masterclass estará disponible en tus archivos de Recto Summit en algún lugar allí. No estoy completamente seguro. Si no lo encuentras después, deberías preguntar en Discord. Muy bien, genial. Esto es lo que hemos hecho hasta ahora. Tenemos una aplicación lenta. Y esta aplicación lenta, cuando escribo en el editor, la aplicación se siente lenta. Y esto es lo que hemos hecho hasta ahora. Grabamos la interacción lenta con las Chrome DevTools, con el panel de rendimiento. Aprendimos que la mayor parte de lo que está sucediendo aquí es código directo. Fuimos al profiler de React y aprendimos que, y grabamos lo que está sucedía durante esa interacción con el profiler de React. Y vimos todos los componentes que se están volviendo a renderizar durante esta interacción. Y en este punto, ya podía ver, ya podía empezar a ver algunos cuellos de botella. Así que miraría esta grabación y pasaría por esta grabación y vería que el componente de la lista de nodos con todos sus hijos tarda 45 milisegundos en renderizarse y es la parte más costosa de la grabación. Y luego el componente no es costoso por sí solo porque por sí solo solo tarda 0.7 milisegundos, pero junto con todos sus hijos, especialmente con todos los botones de nodo, tarda todo el salto de 45 milisegundos, que puede no parecer mucho, pero tengo una laptop M2 Pro en una laptop de usuario promedio que va a ser cuatro o seis veces más lenta. Y así que mi siguiente pregunta en este punto es, vale, pero ¿por qué exactamente se están renderizando estos componentes y qué podemos hacer para evitar que se rendericen? Y así, el siguiente paso que hago para depurar este problema de rendimiento es ir a la configuración del profiler, ir a la pestaña del Profiler y marcar la casilla que se llama grabar por qué se renderiza cada componente durante el perfilado. Y así, si habilito la casilla y si intento grabar la interacción de rendimiento, necesito abrir las DevTools de nuevo. Si intento grabar la interacción de rendimiento que tengo, ahora uno, dos, tres, esta vez vería el mismo árbol de componentes de React. Pero si paso el mouse sobre cualquiera de estos componentes, vería por qué exactamente se renderizó cada uno de estos componentes.

Análisis de la renderización de componentes y optimización

Short description:

Vamos a averiguar por qué se renderiza este componente y qué podemos hacer para solucionarlo. El componente de la aplicación se renderiza debido a cambios, al igual que sus componentes hijos. El componente notesListComponent se renderiza debido a cambios específicos en las props. Podemos optimizar evitando renderizaciones innecesarias. Los componentes de los botones de nodo también tienen props que cambian innecesariamente. Solucionamos esto utilizando callbacks y memoización de los componentes. De esta manera, depuramos y resolvemos un problema de rendimiento. Grabamos y analizamos el rendimiento de la aplicación utilizando los paneles de Rendimiento y Profiler. A continuación, continuaremos optimizando componentes y buscando renderizaciones innecesarias.

Y este es mi siguiente paso. Vamos a tratar de averiguar por qué se renderiza este componente y qué podemos hacer para solucionarlo, ¿de acuerdo? Vale, ¿qué está sucediendo exactamente aquí? Estoy escribiendo en el editor. Eso hace que el componente de la aplicación se renderice. El componente de la aplicación se renderiza porque es lo que ha cambiado. El componente de la aplicación se renderiza y luego se renderiza su componente hijo Dark Mode provider, y ese componente se renderiza porque sus hijos han cambiado. Luego se renderiza el proveedor de contexto. Las DevTools nunca muestran la razón del proveedor de contexto, pero bueno, no es un cuello de botella. Normalmente lo ignoro. Luego se renderiza el componente notesListComponent y se renderiza porque las props notesProp, onYouNotesRequestedProp y onDeleteAllRequestedProps han cambiado. Luego se renderiza el componente de filtrado solo porque su componente padre se renderiza. Luego un montón de botones de nodo, todos estos botones de nodo, se han vuelto a renderizar porque la prop onNotActivated ha cambiado. Y así, en este punto, voy a intentar abordar la solución al problema que estoy observando. Resolver problemas generalmente está fuera del contexto de esta masterclass. Pero solo como demostración, intentemos hacer esto con esta aplicación concreta. Así que ahora voy a intentar... Veo un montón de componentes renderizándose. Y mi pregunta más importante en este punto es si hay algún componente que se renderice innecesariamente y que se pueda evitar renderizar para optimizar la interacción de rendimiento de esta manera. Así que si observo todas estas props que están cambiando, veamos si alguna de estas props está cambiando innecesariamente. Primero veamos cuál es el hook uno en el componente de la aplicación. Tal vez si podemos evitar que el componente de la aplicación se renderice, este árbol completo no se renderizaría. Así que voy a ir al componente de la aplicación y buscar hooks y encontrar el hook uno, que es el hook useState. Vería que el hook useState es el objeto notes y el objeto notes, según el nombre, almacena todas las notas, ¿verdad? Entonces, cuando escribo, el hook número uno cambia, pero probablemente cambia para bien porque supongo que son las notas, no lo sé con certeza, pero está bien que no lo sepa con certeza, solo estoy tomando una visión general de alto nivel de todos los componentes. Entonces, el modo de la aplicación probablemente no se pueda optimizar todavía. El proveedor Darkmap, esto se renderiza porque sus hijos han cambiado, eso nunca se puede optimizar porque los hijos siempre van a cambiar entre las renderizaciones a menos que hagas algunos trucos de optimización específicos raros. NotesList. Bueno, este parece ser más interesante. En el componente NotesList, tengo tres props que cambian. Notes, solo notes requested, solo little requested. La prop Notes probablemente sea la misma, probablemente sea el mismo objeto con las notas que tengo aquí. Puedo confirmarlo más tarde, pero las otras dos props que veo en la lista, solo units requested y solo little requested, parecen ser algunos controladores de eventos, ¿verdad? Y parecen estar cambiando en cada renderización. Entonces, cuando veo esto, esto ya es uno de los patrones de rendimiento comunes que a menudo no veo en las aplicaciones. ¿Podrías, solo con mirar esto, adivinar qué está sucediendo exactamente en la aplicación con estas props? ¿Podrías decirme qué está sucediendo con estas props solo con mirar esta grabación de rendimiento, con estos controladores de eventos que cambian en cada renderización? Sí, Bruno dice que deberían ser memoizados. Sí. Así que solo con mirar esto, y nuevamente, aún no estoy seguro. Ni siquiera he mirado el código, pero ya estoy tomando algunas notas para mí mismo, que bueno, probablemente no se pueda optimizar el componente de la aplicación. El componente de la lista de nodos, parece que una de las props aquí cambia para bien, pero las dos props que se pueden optimizar probablemente se pueden evitar que se rendericen. Podría ir y encontrar dónde se está renderizando ese componente y ahora podría confirmar la hipótesis. Así que tengo el all node activated, y oh no, lo siento, en new nodes requested y en delete all requested, y tenemos estas dos funciones, y sí, parecen funciones que no están memoizadas, que cambian en cada renderización. Entonces, ese es el componente de la lista de nodos, pero la primera prop en la lista de nodos, nodes, es la misma prop, es el hook useState. Ese es el hook useState del componente de la aplicación, y parece que probablemente cambie entre las renderizaciones. Supongo que comienza el estado, por lo que probablemente no podamos optimizar este componente realmente. Así que voy a dejar este componente por ahora y voy a echar un vistazo a sus hijos. Y lo que tenemos aquí es el componente de entrada de filtrado y un montón de componentes de botones de nodo. Y todos los componentes de botones de nodo, excepto el primero, tienen una sola prop que cambia en cada renderización, que es la prop onNodeActivated. Y esto se parece a lo que acabamos de ver con la lista de nodos, ¿verdad? Aquí tenemos dos props que parecen ser controladores de eventos que cambian siempre, y aquí tenemos una prop que parece ser un controlador de eventos que cambia siempre. Entonces, tal vez haya alguna función que no hemos logrado memoizar o algo así. Vamos a echar un vistazo. Así que voy a encontrar un lugar donde se renderiza el componente de botón de nodo. Puedo hacer eso con la búsqueda, o otra forma en que podría hacerlo es haciendo clic en este componente y cambiando a la pestaña de componentes, y simplemente copiando este enlace de origen y yendo a vscode y yendo directamente a esta línea, que está aquí. Y si miro el componente de botón de nodo, si miro cómo se renderiza, vería que la prop onNotActivated es una función que se crea en cada renderización. Entonces, ¿cómo resolvemos esto típicamente? Dime, dime, dime, dime. Sí, usamos callbacks. Entonces, en este caso, en este caso, la función está dentro de un map, por lo que no podemos usar callback directamente aquí porque no se pueden usar callbacks condicionalmente, no se pueden usar hooks condicionalmente, no se pueden usar hooks dentro del map, pero si hago una cosa diferente, si en lugar de pasar onNotActivated, en lugar de pasar una función anónima que llama a onNotActivatedId, si simplemente paso esta función directamente y paso el id directamente y llamo a onNotActivated con el id desde dentro del componente, entonces la referencia de la función probablemente se mantendría igual. Veamos, la prop onNotActivated proviene de NodesList. NodesList obtiene la prop onNotActivated de setActiveNodeId. Y setActiveNodeId proviene de UseState y el callback de UseState siempre es estable. Entonces, esta función siempre debería ser estable. Muy bien, si simplemente paso esta función directamente, en lugar de crear y pasar una nueva función anónima cada vez, y si envuelvo este componente con Memo para decirle a React que este componente no debe volver a renderizarse cuando cambien sus props, entonces, ¿qué sucedería entonces? Iríamos al panel de Profiler, oh, lo siento, iríamos al panel del Profiler y trataríamos de grabar lo que está sucediendo en la aplicación. Ahí vamos. Y luego veríamos la traza y aquí veríamos que todos los botones de nodo que estábamos renderizando antes, ahora están en gris. En lugar de verde o amarillento, ahora están en gris. Y si los inspeccionamos, veríamos que no se han renderizado. Entonces, este es un problema de rendimiento que acabamos de depurar y resolver. Lo que hemos hecho hasta ahora es tomar un problema de rendimiento, grabarlo con el panel de Rendimiento, aprender que la mayor parte de lo que está sucediendo está en el código de React. Porque aprendimos que cambiamos al panel del Profiler y grabamos todo lo que está sucediendo en la aplicación con el panel del Profiler, y aprendimos todos los componentes que se están renderizando. Luego fuimos a Configuración y habilitamos Grabar qué componente se renderizó durante el perfilado y también aprendimos por qué se renderiza cada componente. Y luego, en este punto, mis siguientes pasos serían revisar todos los componentes y tratar de encontrar algunos componentes que se rendericen innecesariamente y tratar de optimizarlos de alguna manera, y en general, las soluciones no son un tema de esta masterclass. Pero aquí acabamos de revisar eso brevemente.

Depuración de rendimiento y análisis de la actividad de la CPU

Short description:

Encontramos uno de los componentes que se renderiza innecesariamente y lo solucionamos. La renderización de React fue la principal causa de la interacción lenta. Grabamos la interacción utilizando DevTools y la analizamos utilizando el perfilador de React. Identificamos los componentes más costosos y optimizamos su renderización. Ahora, pasemos a un ejemplo más grande y complejo.

No entramos en ese período en muchos detalles, ¿verdad? Encontramos uno de los componentes que se renderiza innecesariamente y descubrimos por qué al mirar sus props, y lo solucionamos. Ahora, cada vez que presiono una tecla, en lugar de tomar 50 milisegundos con 100 nodos, solo toma 10 milisegundos. La aplicación debería sentirse mucho más rápida incluso con 700 nodos. Mira, estoy escribiendo y la velocidad de fotogramas es genial y las barras rojas son muy, muy cortas.

De acuerdo, entonces. Hasta ahora, todos estos pasos que he seguido, provienen de mi memoria, ¿verdad? Como esto es lo que hemos pasado hasta ahora, es como lo que he mostrado hasta ahora, es cómo abordo la depuración de aplicaciones, pero todos los pasos que tomo, generalmente provienen de mi memoria, como sé estas cosas y las uso, pero estas cosas no tienen que venir de tu memoria para ti. Para esta masterclass específicamente, preparé este diagrama de flujo que muestra mi proceso de depuración de rendimiento con todas las herramientas que uso y si revisamos este diagrama de flujo, veríamos prácticamente lo mismo que hemos pasado hasta ahora. Tuvimos una interacción lenta y lo que hicimos fue grabar la interacción utilizando DevTools sin la limitación de velocidad de la CPU, pero vamos a habilitar la limitación de velocidad de la CPU para los siguientes pasos. Observamos lo que está sucediendo durante la interacción y vimos que la mayor parte de lo que está sucediendo en la interacción durante la interacción es el código de React.

Ahora podría haber dos tipos de códigos de React y me salto esto, pero más adelante durante la masterclass veremos la diferencia, veremos algunas cosas que el perfilador de React puede capturar y algunas cosas que el perfilador de React no puede capturar, pero en este caso, la mayor parte de lo que teníamos en la grabación era la renderización de React. Así que fuimos al perfilador de React y grabamos lo que está sucediendo en la aplicación utilizando el perfilador de React. Vamos a agregar esto para que sea más explícito. Luego fuimos a todos los componentes utilizando el perfilador de React e intentamos encontrar los componentes más costosos en nuestro caso, para la lista de notas con todos sus hijos y específicamente los componentes de los botones de notas que teníamos cien o 700 componentes que eran baratos por sí mismos, pero teníamos muchos de ellos. Luego intentamos descubrir por qué se renderizaban estos componentes y en este caso, para esto utilicé la configuración de la herramienta Rect, grabar cuando se renderiza el componente, que es bueno en la mayoría de los casos. No muestra cómo cambian exactamente las props, pero muestra qué props cambian a menudo, eso es suficiente. Luego intenté responder, ¿cómo puedo renderizar estos componentes menos veces o renderizar menos de ellos, o no renderizarlos en absoluto? Y una de las soluciones posibles es desvincular el metal, lo que en este caso implicaba envolver las props con un callback y envolver el componente en sí con memo. Así que esta es solo una rama del diagrama de flujo de depuración.

Ahora voy a enviar el enlace a los chats. Lo que hemos pasado hasta ahora durante la última hora fue esta aplicación simple con una sola interacción lenta aislada. Perfilamos esta interacción y aprendimos que durante esta interacción, la mayor parte de lo que está sucediendo es una renderización de React. Y la renderización de React consistió principalmente en unos pocos cientos o cientos, dependiendo de cuántos teníamos, de componentes de botones de notas. Y lo que hicimos fue descubrir por qué se renderizaban los componentes de botones de notas y lo solucionamos. Evitamos que se renderizaran, lo que hizo que la interacción fuera mucho más rápida. Así que en este punto, me pregunto, ¿tienen alguna pregunta sobre lo que hemos pasado hasta ahora, sobre esto o sobre los diagramas de flujo de depuración que usaremos más adelante para todos los ejemplos siguientes? Este es un buen momento para desactivar el silencio y hacer una pregunta en voz alta, si lo desean. No hay preguntas. No hay preguntas tres. No hay preguntas dos. No hay preguntas uno. Muy bien. Oh, espera. Oh, algunos chats. No. Sí. De acuerdo. No hay preguntas. Muy bien. En este caso, echemos un vistazo a otro ejemplo, que en este caso es una carga de trabajo más grande y mucho más compleja. Entonces, para usar este ejemplo, voy a ir a la aplicación del editor de widgets. Voy a instalar las dependencias en esa aplicación y voy a ejecutar yarn start. Y allí, una vez que la aplicación se inicie, lo que llevará unos segundos, obtendré este panel de control de widgets con un montón de widgets con los que puedo interactuar. Esta aplicación es una aplicación real de código abierto de un cliente con el que trabajamos en el pasado. El cliente amablemente me proporcionó esa aplicación para que la use en las masterclass. Esta aplicación se ralentizó artificialmente y tiene el siguiente problema de rendimiento. Si abres cualquier configuración de cualquier campo de texto y abres el menú desplegable de tipo de datos, que especifica el tipo de campo, y lo cambias de texto a texto, básicamente no lo cambias en absoluto, obtendrás un solo pico relativamente lento de actividad de la CPU, un retraso relativamente lento. Puedes verlo en el panel de velocidad de fotogramas. Ahora, en esta computadora portátil, en mi computadora portátil, esto se siente bastante rápido, pero eso es porque estoy usando Apple Silicon con un procesador M2 Pro, así que, por supuesto, va a ser rápido. Para los usuarios del mundo real, esto es mucho más lento. Entonces, para reproducir eso, para reproducir lo que realmente sienten los usuarios del mundo real, voy a cambiar al panel de Rendimiento y voy a activar la limitación de velocidad de la CPU 4x. Y ahora, si abro el menú desplegable de texto y selecciono nuevamente el menú desplegable de texto, veré este pico de actividad de la CPU, veré que el hilo principal está bloqueado en el panel de velocidad de fotogramas. Ves que no puedo mover el mouse porque va a desaparecer, pero ves la barra roja y la barra amarilla y todo el tiempo es el hilo principal bloqueado. Y también, si intento interactuar rápidamente con la aplicación después de este campo de texto, será lento y lento y muy, muy, muy molesto. Así que intentemos depurar este problema de rendimiento. ¿Cómo lo hago? Echemos un vistazo al diagrama de flujo. Lo primero que hago cuando tengo un problema de rendimiento es grabar el problema de rendimiento utilizando DevTools, idealmente habilitando la limitación de velocidad de la CPU para imitar el rendimiento de los usuarios reales si usas Apple Silicon o un potente procesador Intel moderno. Tengo la limitación de velocidad de la CPU de 4x habilitada y lo que voy a hacer es hacer clic en grabar y voy a reproducir el problema de rendimiento. Luego voy a detener la grabación y ver qué está sucediendo en la aplicación durante la interacción lenta. Veamos qué sucede aquí. En la grabación, lo primero que miro es la fila de la CPU y la fila de la CPU me muestra cuándo la aplicación estaba ocupada. Y en este caso, veo múltiples picos diferentes de actividad de la CPU, que pueden corresponder a diferentes cosas. Entonces, para averiguar cuál de estos realmente me importa, qué es lo que realmente necesito, también voy a mirar los fotogramas, que ves ahora. Cada vez que muevo el mouse sobre la fila de la CPU, Chrome también me muestra cómo se ve exactamente la aplicación en ese momento concreto de la renderización. Entonces, lo que necesito encontrar entre estos pocos picos es el momento en que hago clic en el valor de texto en el menú desplegable y, por lo tanto, el hilo principal estaba ocupado durante un período de tiempo significativo. Y esto, bueno, aquí muevo el mouse y Chrome me muestra eso porque el cambio de posición, ¿verdad? Aquí abro el menú desplegable y eso causa cierta actividad de la CPU. Puedes ver que las barras no están llenas hasta arriba, lo que significa que la CPU no estaba ocupada al 100%. Y luego aquí en este pico, en este pico el pico comienza y luego en algún lugar de este pico, el menú desplegable desaparece y luego se cancela el pico. Entonces, esto parece ser el momento en que hice clic en el menú desplegable. Acerquémonos a eso. Este es el pico de actividad de la CPU.

Análisis del Pico de Actividad de la CPU

Short description:

El pico de actividad de la CPU revela múltiples tareas independientes que bloquean el hilo principal y hacen que la aplicación parezca ocupada. Analizar tres tareas grandes con resaltados rojos y triángulos nos ayudará a entender qué está sucediendo en cada tarea.

El pico de actividad de la CPU duró alrededor de 6 o 700 milisegundos, mirando esto, también podría medirlo directamente en el panel principal si mantengo presionado el botón shift. Mantén presionado el botón shift y arrastra esto. Sería capaz de medir la duración que sí, 786 milisegundos, bastante cerca. Y entonces veamos qué sucede durante este pico de actividad de la CPU. Así que lo que tengo aquí sucediendo es que tengo múltiples tareas independientes. Cada tarea es un período ininterrumpido cuando el hilo principal estaba ocupado haciendo algo. Si obtengo múltiples tareas, eso significa que el navegador tal vez tuvo la oportunidad de renderizar algo entre las tareas, o tal vez simplemente estaba inactivo entre las tareas, pero la tarea aún bloquea los hilos principales. Y si obtengo múltiples tareas grandes seguidas, eso todavía significa que la aplicación se siente como si estuviera ocupada. Entonces, en este caso, tengo tres tareas grandes. También podrían obtener esto. Resaltados rojos y los triángulos rojos, y es una tarea larga. Sí, bueno. No lo sé. Solo en caso de que sea útil, nunca lo miro realmente. Pero tenemos tres tareas largas, y tratemos de averiguar qué está sucediendo en cada una de esas tareas.

Analizando Eventos de Clic y Microtareas

Short description:

Al analizar la grabación, tomo capturas de pantalla para anotar las partes concretas. La primera tarea son los Eventos de Clic, que desencadenan la ejecución del código de React. El manejador de eventos onClick despacha código JavaScript. El manejador de eventos en sí es corto, pero hay más código JavaScript ejecutándose después. La segunda parte es la función de ejecución de microtareas, que indica una promesa resuelta. La devolución de llamada que se ejecuta es de React DOM development. La siguiente función es la función de renderizado de raíz sincrónica, que indica un renderizado de React. Siguiendo la primera rama del gráfico de llamas revela el renderizado de React. La función de commit root incluye commit mutation effects, commit layout effects, y flash passive effects. Dependiendo del tiempo que cada función tome, se utilizan diferentes enfoques de depuración.

Y una cosa que me gusta hacer aquí, cuando tengo muchas cosas en la misma página, es que me gusta simplemente tomar una captura de pantalla de lo que está sucediendo en la aplicación. Y me gusta guardar esa captura de pantalla en un, ¿por qué es transparente? Vaya, eso es algo... Oh, claro, está tomando una captura de pantalla de... Ooh, está tomando una captura de pantalla de mi compartición de pantalla. Vaya. Bien, ahora tengo la captura de pantalla de la ventana. Así que lo que me gusta hacer es simplemente tomar una captura de pantalla de la grabación con la que estoy trabajando y luego guardarla en algún lugar y simplemente anotarla directamente en la captura de pantalla para recordar las partes concretas que... Como las cosas concretas que están sucediendo durante la grabación.

Así que hagamos eso. Voy a cambiar al flujo de trabajo de debugging y voy a lanzar un rectángulo. Vale, esta va a ser mi área de juegos con el... donde voy a anotar mis capturas de pantalla y voy a soltar mi captura de pantalla justo aquí e intentaré anotarla aquí mismo. Y entonces veamos qué está pasando aquí. Así que la primera tarea que tenemos aquí son los Eventos de Clic. Hago clic en el desplegable y el navegador comienza a manejar ese clic. Durante ese clic, obtengo dos partes más pequeñas, dos rectángulos más pequeños, la Llamada de Función y la Ejecución de Microtareas. Así que la Llamada de Función parece ser principalmente algún código de React. Código de React. React, React, React. Evento de React, clic. Compilar código. Llamar a la devolución de llamada. Así que la mayoría de esto es algún código de React desencadenando los eventos de clic sintéticos de React, luego compilando algún código durante 20 milisegundos también. Y luego llamando a alguna devolución de llamada y luego llegando a nuestro código, que podría notar que es nuestro código porque es de un color diferente, pero entonces nuestro código sólo toma como 12 milisegundos de este tiempo. Y entonces, bien, lo que tengo aquí es que tengo el manejador de eventos onClick que aparentemente despacha, como maneja mi clic en el desplegable y luego despacha todo este JavaScript que se ejecuta después. Y podría echarle un vistazo sólo para saber qué hay. Así que esto es un onClick en el desplegable. Bien, sólo maneja algún manejador de clic de opción. Esto parece ser algún desplegable genérico. Entonces, bien, algún anónimo en el desplegable. Oh sí, este es el manejador de clic de opción, useCallback, set isSelected, set isOpen, onSelect, onSelect llama a cuatro funciones, y luego despacha setState es probablemente la devolución de llamada de setState. Y entonces el onItemSelect es mi lógica de aplicación real, probablemente, updateProperty. Oh sí, y aquí llegamos a la lógica de la aplicación, que es onPropertyChanged algo así, o tal vez esto es, onPropertyChanged. Bien, así que sólo hay algo de lógica de manejador de eventos onClick sucediendo. Y el manejador de eventos por sí solo es realmente corto. Son sólo 12 milisegundos. Pero lo que está sucediendo después es mucho más Javascript. Y supongo que en este punto que todo este Javascript está sucediendo porque nosotros, el manejador de eventos onClick lo detuvo. Pero no voy a profundizar en eso todavía. Sólo estoy tomando una visión general de alto nivel de todo lo que está sucediendo, pero voy a anotarlo en el rastro, en la captura de pantalla que tengo. Así que hagamos la anotación. Amarillo, sin campo. La primera parte es sólo el manejador de eventos. Así que eso es todo. Bien. ¿Cuál es la segunda parte? La segunda parte es la función de ejecución de microtareas. Ahora, como siempre que veo la función de ejecución de microtareas, lo que normalmente significa es que hubo alguna promesa que se resolvió. Y lo que se está ejecutando bajo la ejecución de microtareas es alguna devolución de llamada de promesa que se programó pero algunos otros códigos y como ahora la promesa se resolvió y por lo tanto ese código se está ejecutando. En este código, la devolución de llamada que parece estar ejecutándose viene de React DOM development. Así que podría hacer clic en él para ver qué es exactamente lo que se programa. Y vería la función llamada programar microtareas que viene de React DOM development que programa alguna función. Um, así que realmente no necesito saber esto. Bien, eso es sólo algo de las entrañas de rect. Voy a seguir con esto, pero luego en algún momento, empezaría, seguiría con las entrañas de rect y notaría uno de los tres nombres de función que recuerdo muy bien porque es realmente útil durante mi perfilado de rendimiento. Y la primera de estas funciones es la función de renderizado de raíz sincrónica. Así que siempre que veo la función de renderizado de raíz en el rastro, lo que sé es que todo lo que está bajo esta función es un renderizado de componentes de rect. Podrías encontrar esto en la referencia de las entrañas de rect. Para todas las versiones relevantes de rect, como rect 16, rect 17, rect 18, siempre que veas la función de renderizado de raíz sincrónica en las entrañas de rect, eso significa que está sucediendo un renderizado de react. Que react está renderizando todos los componentes. Y eso a su vez significa que siempre que veas estos, para averiguar qué está sucediendo aquí en esta parte de la grabación, deberías seguir la primera parte, la primera rama de la camiseta de llamas porque lo que está sucediendo aquí es el renderizado de rect. Ahora, la siguiente función que tengo aquí es commit root, y bajo commit root, tengo commit mutation effects, que en realidad no sé qué hace. Creo que simplemente modifica el DOM, basado en el nombre. Luego commit layout effects, que es la segunda función que conozco muy bien, que es la función, que desencadena o revisa el efecto de diseño compañía que monta y compañía data actualiza las devoluciones de llamada. Y luego tengo la tercera función, que recuerdo muy bien, que se llama flash passive effects, que llama a todas las funciones de use effect. Y conozco muy bien estas funciones, porque dependiendo de cuánto tiempo tome cada una de estas, depuraría lo que está sucediendo aquí de manera diferente. Si la mayor parte del tiempo es tomado por la función de renderizado de raíz sincrónica, como lo fue en nuestra anterior, no tomando la aplicación y como todavía parece, parece ser el caso aquí. Si la mayor parte del tiempo es tomado por la función de renderizado de raíz sincrónica, entonces voy a seguir la primera rama del flujo de trabajo. Y voy a usar el perfilador de React. Pero si la mayor parte del tiempo es tomado por commit layout effects o flash basic effects, seguiría la segunda rama de las gráficas de llamas, y trataría de averiguar qué esfuerzos son y cómo prevenir que se ejecuten. Pero llegaremos a eso más tarde.

Analizando el Tiempo de Renderizado y la Ejecución de Tareas

Short description:

La mayor parte del tiempo se dedica a renderizar los componentes de React. El proceso utilizado aquí ayuda a entender qué consume más tiempo antes de decidir en qué centrarse. La primera tarea se anota con colores para el renderizado de React y los efectos. La segunda tarea consiste en llamadas a funciones, llamadas a Redux SEGA y algo de código de bajo nivel. La tercera tarea se ejecuta debido a un temporizador activado, con una característica de flecha conveniente para localizar la instalación del temporizador.

En este punto, parece que se gasta la mayor parte del tiempo en la función de renderizado de raíz sincrónica. Y eso significa que la mayor parte del tiempo se gasta renderizando los componentes de React. Y voy a guardar eso también en la anotación. Así que de nuevo, sin profundizar demasiado, sólo recogiendo la imagen general para averiguar qué consume la mayor parte del tiempo y por dónde empezar. Porque en realidad, una cosa que solía hacer cuando empezaba a hacer rendimiento es que encontraría la primera cosa que parecía entender. Me gustaría, Ooh, esto parece ser como el componente que reconozco, vamos a profundizar en él. Y luego simplemente gastaría un montón de tiempo tratando de optimizarlo sin entender realmente cuánto tiempo lleva. Y así este proceso, que yo, que hacemos aquí, que hacemos ahora es el proceso que uso para entender qué consume realmente la mayor parte del tiempo antes de elegir el juego antes de elegir en qué centrarse. Bueno, esto es realmente incómodo de usar. En realidad uso una aplicación diferente para esto normalmente, que es simplemente una aplicación de dibujo para iPad. Pero está bien, esto es como vamos a hacerlo, vamos a hacerlo rojo para el renderizado de React. Así que tenemos rojo igual a renderizado de React. Y luego estas partes son sólo algunos efectos, ¿verdad? Commit layout effects uno, commit layout effects dos, FlushBase effects tres, sí. Todas estas cosas son sólo efectos. Vamos a hacerlos verdes. ¿Tenemos que hacer esto? Gente en esta llamada, lo siento. Esto es, esto podría ser confuso. Dependiendo del tipo de tiendas. El verde va a ser los efectos de React. Bien, esto, esta fue la primera tarea. Acabo de anotar la primera tarea. Genial. Continuemos con la segunda. Así que la segunda, la segunda gran tarea, consta de dos cosas. Primero, hay alguna llamada a función, que tarda 16 milisegundos y algún intermediario de trabajador a lo que sea que sea. Intermediario, no sé, parece ser algún código de bajo nivel. Luego, ooh, un montón de llamadas a Redux SEGA. Algo de color diferente. Bueno, hay algo, eso es sólo, vale, algo también, algunos códigos de bajo nivel, observable único. Sí, no sé qué es eso. Alguna biblioteca, reductor central, reductor reductor. Bien. Esto parece ser el código de la aplicación porque tiene un color ligeramente diferente y porque el nombre finalmente no parece ser código de función. Oh, esto es sólo un apropiado para el reductor. Bien, eso sigue siendo, ¿qué pasa con esto? No, eso es emir. Emir produce todavía código de función. Vale, código de función, emir, emir, emir, emir. ¿Algo nuevo aquí? No, no react redux, react redux, react redux. Vale, ¿qué tenemos aquí? Estos 13 milisegundos parecen ser sólo algo de código relacionado con redux, ¿verdad? Así que de nuevo, no voy a profundizar en eso. Podría averiguar qué acción es esa. Como qué está pasando realmente dentro de redux. ¿Por qué emir tarda tanto? Probablemente tarda tanto porque hay algunos objetos grandes que está duplicando o lo que sea. Pero en este punto, sólo voy a poner una nota. Esta cosa es sólo código de redux. Bien, veamos lo siguiente. Lo siguiente que tenemos, ooh, tenemos una imagen bastante similar por cierto, similar a lo que acabamos de ver. Lo que tenemos aquí es que tenemos más código de desarrollo de regedom y tenemos, de nuevo, renderRootSync, commitRoot, renderRootSync, commitRoot. renderRootSync, commitRoot, renderRootSync, commitRoot. Lo mismo que vimos en la tarea anterior. Así que cuando veo esto, en realidad me pongo muy contento porque esto significa que probablemente estamos ejecutando el mismo código dos veces. Lo que significa que si pudiéramos averiguar por qué se está ejecutando dos veces, podríamos evitar que se ejecute dos veces y ahorrar 250 milisegundos sólo haciendo eso. Así que, en este caso esto no garantiza que se estén renderizando los mismos componentes, ¿verdad? Porque estas funciones son sólo algunas funciones de desarrollo de regedom, pero sólo la forma de estas cosas siendo muy similares, como mira esto, esta cosa tiene una pata larga. Esta cosa tiene una pata larga. Esta cosa tiene una pata gruesa. Esta cosa tiene una pata gruesa. Como todas estas cosas pareciendo similares que esto ya me dice que, ooh, bien esto parece probablemente el mismo código ejecutándose dos veces. Lo cual, estoy contento por esto. Así que, vamos a mirar para confirmar esto. Render root sync, eso es un renderizado de React. Commit layout effects, eso es use layout effect compañía que no compañía a la base de datos. Flash passive effects, eso es use effect. De nuevo, render root sync, commit layout effects, sí, parece ser en su mayoría la misma cosa que teníamos allí. Así que sólo voy a seleccionar estos cuatro y moverlos aquí y ajustarlos un poco porque el tiempo es un poco diferente. Pero en general esto parece ser lo mismo. Yay, y acabamos de averiguar qué está pasando. Averiguamos a alto nivel qué está pasando en la segunda tarea, ¿verdad? Ahora echemos un vistazo a la tercera tarea. La tercera tarea, se ejecuta porque se disparó algún temporizador. Y por cierto, puedes ver esta pequeña flecha que tengo aquí. Flecha que me lleva al lugar donde se instaló el temporizador. Esta es una característica muy conveniente de DevTools, pero por alguna razón por defecto está apagada.

Capturando Errores en DevTools

Short description:

Para capturar un error específico en DevTools, habilita la casilla 'iniciadores de eventos de línea de tiempo' en la configuración de DevTool. Esto mostrará errores convenientes que apuntan a la ubicación del código cuando se programa un temporizador. Sin embargo, hay algunos errores de DevTools que pueden afectar la precisión de la grabación, como las llamadas a funciones sin etiquetar y las capturas de funciones que faltan. Para solucionar estos problemas, puedes intentar usar una versión más antigua de Chrome, como Chrome 90. Comparar grabaciones puede ayudar a identificar estos errores y su impacto en las llamadas a funciones y la ejecución del código.

Entonces, si quieres obtener este error en tus DevTools, lo que necesitas hacer es ir a la configuración de DevTool, experimentos, desplázate hasta, oh sí, en realidad no te desplaces, pero encuentra la casilla que dice iniciadores de eventos de línea de tiempo y márcala. Necesitas tenerla marcada. Y luego, si la tienes marcada, lo que verías es que para cada temporizador, para cada solicitud de animation frame, llamada para cosas así, verías estos errores muy convenientes que te señalan el lugar donde estaba el code, cuando se programó el temporizador.

Pero bueno, en este caso tengo un temporizador y este temporizador toma, el manejador del temporizador toma 90 milisegundos. Y la mayoría de los códigos aquí también parecen ser redux, algunas cosas de redux, alguna llamada a función, redux, redux, redux, redux, parche de redux, rect redux, rect redux, sigue bajando realmente bajo, rect redux, alguna función anónima, nombre, desarrollo de rect DOM, nombre TSX. Ooh, ¿hay algún selector costoso? Confuso.

Entonces, por cierto, aquí podrías observar otro error de DevTools que probablemente experimentarías cuando estás perfilando cosas. Así que cada vez que obtienes, como cada vez que veo esta extraña llamada a función sin etiquetar en medio de un gráfico principal, es como una cosa, ¿verdad? En medio de un frame con un montón de espacio vacío debajo de él, lo que realmente parece estar sucediendo aquí es que DevTools no logró capturar las llamadas a funciones reales que están sucediendo durante todo este tiempo. Elevé el error sobre esto, y afortunadamente nadie lo arregló aún, pero eso sucede con el perfilado de Rheq de vez en cuando, esto es muy desafortunado, yo, esto es con lo que voy a lidiar porque esconde lo que está sucediendo en el rastro. Y la única forma de lidiar con esto que tengo es cambiando a una versión más antigua de Chrome, que mi referencia es simplemente Chrome 90, normalmente uso Chrome 90, e intento grabar el rastro allí porque las versiones más antiguas no son, como supongo que funcionan de manera diferente, por lo que no siempre se ven afectadas por el cambio.

Entonces, intentemos hacer eso porque mira, hay una llamada a función amarilla, sin etiquetar, como cualquier nombre de función aquí, y hay otra llamada a función amarilla sin etiquetar sin ninguna asociación aquí con un montón de espacio vacío debajo y algunas referencias aleatorias. Y esto es simplemente super, super raro. Como, o no super, super raro, es como lo vi un montón de veces, así que sé que esto es solo un error de DevTools. Entonces, intentemos perfilar esa parte correctamente. Y para hacer eso, voy a buscar versiones antiguas de Chromium, y voy a encontrar cualquier enlace que me permita descargar versiones antiguas de Chromium, que yo estaba, oh sí, normalmente uso este enlace. Parece muy sospechoso, pero en realidad enlaza con el oficial almacenamiento común de data, googleapps.com, así que está bien. Frederick sugiere probablemente usar el Firefox Profiler, que en realidad es una buena idea. Nunca lo he probado. Probablemente debería funcionar, pero no voy a arriesgarme ahora. Así que solo voy a buscar un juego mac irm90 algo. No, dame el 90, por favor, dame el 90. ¿Por qué no puedo ver el 90? Bueno, lo que sea, tomaré el 90. 92, 92, 92. Sí, este. Tomemos ese. Voy a descargar. Debería descargar Chromium. Abre el archivo. Oh, espera, no, no, no, oh no. Espera. Correcto, porque es el. Necesitas hacer clic derecho y, necesitas eliminar los, algunos atributos. Espera, ¿cuáles son los X-utters? Sé que puedes ver mi historial de línea de comandos. Luts Chrome. Chrome Mac. Oh, Chrome Mac cinco. Puedes ver que he hecho, esta no es mi primera vez haciendo esto. Desde tu mapa. Y ahora debería supuestamente abrir, sí. Así que esto es una cosa de Mac OS, simplemente sucede si tienes muchas pestañas que están como sin firmar o algo así, como no el canal oficial de publicación o lo que sea. De todos modos.

Mm. Ahora, si yo tomo mi URL y voy a mi antiguo Chromium y abro la aplicación aquí y luego intento grabar esta misma interacción usando el antiguo Chromium. Así que abre. Abre el desplegable, haz clic en grabar, haz clic en texto, oh no, no habilité el estrangulamiento de CPU. Detén la grabación. Espera, déjame hacerlo con estrangulamiento de CPU para que obtengamos la misma imagen. Correcto, abre, graba. Detén la grabación y detén. Entonces lo que veré es que obtendré, de nuevo, las mismas tres. Espera, oh. Espera. Siguiente pantalla. Ah. Eso es lo que puedo obtener por tener una pantalla extra. Vería las mismas tres cosas que vi en la grabación anterior, ¿verdad? Y aquí está mi temporizador de fuego que estaba buscando. Oh no, tiene el mismo error. Maldita sea, realmente necesito Chrome 90. Pero como sea, no voy a gastar más tiempo en esto. Esto es algo con lo que normalmente trabajo obteniendo Chrome 90, tal vez es demasiado antiguo, no puedo cargarlo desde allí. Pero realmente podrías ver que es, como una vez que empiezas a verlo más a menudo, claramente verías que este es un error de Chrome. Porque si comparas las dos grabaciones, compara sobre estas llamadas a funciones, estas extrañas llamadas a funciones sin etiquetar están sucediendo. Verías que están sucediendo en lugares muy diferentes. Dirías que la mayoría del code se ve igual. Correcto, tenemos el CarseB, se divide en dos funciones aquí. Pero este es otro error de DevTools, en realidad se solucionó. A veces DevTools en el pasado solía, todavía lo están, ¿todavía lo están haciendo? No lo sé. Pero a veces cuando tendrías una función larga, una única función larga, DevTools dividiría esa función en dos patas separadas, lo cual también es confuso. Pero si miras el code, verías que es prácticamente el mismo code, CarseB, yada, yada, yada, como todo lo mismo, la misma pila de ejecución, ¿verdad? Excepto que aquí, estas extrañas llamadas a funciones sin etiquetar suceden justo después de la siguiente función. Y aquí, las funciones simplemente continúan.

Analizando Renders y Componentes Costosos

Short description:

Esta parte discute un error de captura de Chromium DevTools y el proceso de análisis de las partes más costosas de la ejecución de JavaScript de la aplicación y el renderizado de React. Se utiliza el Profiler de React para identificar los componentes más costosos y los re-renders. Se habilita el estrangulamiento de la CPU para simular condiciones del mundo real. El enfoque está en entender los renders y componentes más costosos en la aplicación.

Entonces, lo que esto me dice es que esto es un error de captura de Chromium DevTools. Como, fallaron en capturar las funciones para algunas páginas. Entonces, de todos modos, solo voy a, esto no es la parte más costosa. Entonces, lo que voy a hacer es simplemente voy a volver a mi grabación a mis anotaciones. Simplemente voy a marcar eso con, como, signos de interrogación. Como, signos de interrogación, probablemente en su mayoría reducts, lo que sea que esté sucediendo allí no estoy completamente seguro. Como esto. Bien.

Entonces, ahora he hecho un rastro con el dolor performance, y he grabado todo lo que sucede allí. Y he analizado todo lo que sucede en la aplicación a un alto nivel, en el nivel más alto, en un nivel superior, y como obtuve una imagen de alto nivel de lo que está sucediendo en la aplicación. Entonces mi próximo paso es averiguar cuál es la parte más costosa de lo que está sucediendo en la aplicación. Así que grabando la interacción del usuario DevTools. Y ahora la interacción, ¿es en su mayoría renderizado directo? ¿Es en su mayoría ReactFX? ¿Es en su mayoría otro JS o es estilo o diseño o cómics? Entonces, si miro a través de esto, vería que este controlador de eventos es en su mayoría solo otro JS. Este redux code también es otro JS. Esto es lo que sea, no sé qué está pasando aquí. Esto también podría ser también React code bajo la cosa. No lo sé con seguridad. Estas cosas rojas son el React renderizando code y estas cosas verdes son el ReactFX code. Entonces, la parte más costosa de todo esto parece ser el React renderizando code. Entonces, simplemente me voy a centrar en eso primero. Y veamos qué necesitamos hacer a continuación. Entonces, si es React renderizando, lo cual confirmamos buscando render root sync, a continuación, necesitamos responder, la siguiente pregunta que necesitamos responder es ¿cuáles son los componentes más costosos o los componentes que se renderizan con más frecuencia y toman más tiempo? Y para responder a eso, vamos a usar Rector Filer y simplemente vamos, luego repasamos todos los renders grabados y tomamos notas, tomamos notas como esta. Entonces, hagamos justamente eso. Estoy volviendo al panel de performance y voy al profiler. Y ahora lo que voy a hacer es, voy a grabar la misma interacción usando, dando mis dev tools. Aquí está. Usando el Rector Filer. Entonces, voy a hacer clic en grabar. Bueno, esto definitivamente es un error de DevTools. Mira, no funciona ni siquiera en chromium adecuado, no solo en Arc. ¿Por qué harían esto? O como, no lo sé. Lo siento, simplemente tiene errores todo el tiempo. Es triste, estoy triste. De todos modos, voy a grabar la interacción que usamos en el recto filer. Voy a mirar lo que está sucediendo en recto filer y oops, oops. Ignora lo que acaba de suceder. Voy a ver 19 re-renders que suceden después de un solo clic en el único desplegable. Ahora, un re-render no es necesariamente malo, si es barato, pero algunos de estos re-renders parecen ser más costosos que otros. Podría ver esto por la altura de estas barras. Entonces, veamos qué re-renders son los más costosos. Entonces, el primero tomó solo 1.5 milisegundos. Eso es barato. Eso es barato. Eso es barato. Este tomó bastante tiempo. Esto tomó 14 milisegundos también sin estrangulamiento de CPU. ¿Verdad? No tengo habilitado el estrangulamiento de CPU, por lo que los números pueden parecer bajos, pero ellos son peores para los usuarios del mundo real. Luego, otro re-render que tomó 7 milisegundos. Luego barato. Otro 16.7, otro 7. ¿Algo más? Sí, ahora todos estos restantes son solo de uno o unos pocos milisegundos de duración. Entonces, solo para obtener la imagen que es más cercana a lo que tienen los usuarios reales, voy a volver y habilitar el estrangulamiento de CPU y grabar esta interacción. Espera, necesito abrir el desplegable primero. Graba la interacción de nuevo. Y entonces obtengo 14 renders por alguna razón. Tal vez alguna diferencia en los códigos de la aplicación, pero todavía obtengo cuatro renders costosos, que ahora están tomando más tiempo, y un montón de renders baratos, que pueden o no ser significativos, solo algunos componentes de renderizado. Entonces, lo que voy a hacer ahora es que voy a centrarme primero en los renders costosos. En realidad, no. No voy a centrarme primero en los renders costosos. Voy a empezar por los renders costosos. Y voy a repasar todos los componentes que tenemos en los renders costosos primero y luego renders baratos, e intentar tomar notas de la misma manera como se describe aquí, encontrando los componentes más costosos. Bien. Entonces, básicamente repitiendo la misma cosa que hicimos aquí. En el paso anterior, grabamos, descubrimos las partes más costosas de la ejecución de JavaScript del panel de performance. Y ahora vamos a descubrir las partes más costosas del panel Req Profiler. Entonces, hagamos estadísticas compartidas. Y una cosa que me gusta hacer cuando tengo un montón de renders realmente baratos que probablemente no sean realmente significativos. Una cosa que me gusta hacer es que me gusta volver a la configuración de devtools y hacer clic en casillas de verificación altura compromete por debajo de 1 milisegundo o 2 milisegundos o lo que sea. Vamos a ponerlo en 1. Vamos a ponerlo en 2.

Analizando Renders Costosos en el Perfilado de React

Short description:

En este render, el componente del editor tomó 7 milisegundos y el componente del editor de widget tomó 44 milisegundos. El editor de widget es costoso. Vamos a copiar ese nodo y escribirlo aquí. Esto fue en Chrome DevTools, y el siguiente paso es el paso dos del perfilador de React.

No lo sé. Entonces tendremos solo 9 renders aún visibles. Lo que eso hace es que filtra eso oculta los renders baratos. Llegaremos a ellos más tarde. Pero por ahora, solo quiero centrarme en los costosos. Así que veamos qué está pasando aquí. Tenemos el primer render costoso. Lo que está pasando en este render es tenemos el componente del editor que tomó 7 milisegundos con todos sus hijos, ¿verdad? Y el componente del editor de widget tomó 44 milisegundos, ¿OK? Ese editor de widget es realmente costoso. Así que voy a copiar ese nodo y escribirlo aquí. Correcto. Así que esto fue rest react, oh lo siento, Chrome DevTools, y esto va a ser el paso dos del perfilador de React. Muy bien, entonces cuando la interacción se haya optimizado.

Analizando Renders de Componentes y Optimización

Short description:

El componente Widgets Editor se renderizó dos veces, tardando un total de 84 milisegundos. La vista Property Pane View se renderizó dos veces, tardando 56 milisegundos. El componente Table se renderizó cuatro veces, tardando 80 milisegundos. Otros componentes, como Positioned Container, también se renderizaron varias veces. El objetivo es identificar los componentes más costosos y optimizar su renderizado. En este caso, investigamos el componente Widgets Editor y sus hooks. Sin embargo, DevTools puede informar de hooks que no existen en el componente debido a las limitaciones de la visibilidad del Rack Profiler en los hooks personalizados.

Entonces, cuando hago clic en el texto donde, donde te encuentras en el menú desplegable. Primero tengo el renderizado del encabezado del editor. Entonces, el encabezado del editor se renderizó, si hago clic en él, puedo ver que se renderizó dos veces aquí y aquí. El encabezado del editor se renderizó dos veces. La primera vez tomó, entonces esta vez, 44 milisegundos, no es el tiempo del encabezado del editor, sino que es el tiempo del renderizado completo. Entonces, necesito hacer clic en esto para ver cuánto tiempo tomó. Entonces, la primera vez tomó 7 milisegundos, y la segunda vez también tomó 7 milisegundos. Entonces, se renderizó dos veces, x 7 milisegundos cada una, lo que significa que tomó 14 milisegundos en total. Muy bien.

A continuación, el siguiente componente que se renderizó fue el editor de widgets. El editor de widgets también parece haberse renderizado dos veces. Entonces, el editor de widgets se renderizó dos veces. x, la primera vez fueron 44 milisegundos, la segunda vez fueron 41 milisegundos. Solo voy a tomar, digamos, 42. Se renderizó dos veces x 42 milisegundos cada una, lo que nos da 84 milisegundos. Entonces, ese fue el primer renderizado, ¿verdad? Ahora he terminado con el primer renderizado. Echemos un vistazo al segundo renderizado. En el segundo renderizado, tengo la vista del panel de propiedades renderizando y tengo los widgets de la tabla, el componente de la tabla volviendo a renderizar. Entonces, la vista del panel de propiedades también se renderizó dos veces. Dos veces x 8, 29, 27, 28 milisegundos cada una, lo que nos da 56 milisegundos. Y luego el componente de la tabla, oh mira, la tabla se renderizó cuatro veces. Oh sí, claro. La tabla, la primera y la tercera vez, es parte de este renderizado del editor de widgets. Entonces, no sé, solo voy a escribirlo. Voy a anotar todos los renderizados porque si optimizamos la tabla, la optimizaremos en todas las cuatro. Entonces, el editor de widgets también obtendrá, como este renderizado también será más barato si optimizamos la tabla. Entonces, voy a sumar los cuatro renderizados. Veamos cuánto tiempo lleva. 20, 20, 20 y 20, ¿verdad? La tabla se renderizó dos veces, x20ms cada una, oh lo siento, cuatro veces, igual a 80ms. Ese es un componente costoso. Y entonces, simplemente sigo pasando por los renderizados de esta manera y sigo encontrando los componentes que se renderizan muchas veces, como componentes baratos renderizados muchas veces o por ejemplo aquí ves el contenedor posicionado. Como, este es el renderizado número seis. Tenemos un montón de instancias de contenedores posicionados, una, dos, tres, cuatro, cinco, seis. Y cada una de estas instancias también parece haberse renderizado cuatro veces, parece ser. Entonces, si hago clic en esta instancia, sí, puedo ver cuatro renderizados. Si hago clic en esta instancia, también puedo ver cuatro renderizados, etcétera, etcétera. Entonces, de nuevo, esto también podría ser significativo. Contenedor posicionado. Entonces, hay cinco instancias, cinco instancias separadas. Cada una de estas instancias parece haberse renderizado cuatro veces. Como, si hago clic en cualquiera de ellas, veo cuatro renderizados. Vale. Las duraciones parecen ser diferentes, ¿verdad? Como, esto toma dos milisegundos en cada renderizado, pero esto toma 20 milisegundos en cada, oh no, no en cada renderizado. Entonces, esto es un poco más difícil de, esto necesitaría un poco más de tiempo para calcular, pero como, no sé. Si estimo, como, ¿qué podría ser? Bueno, no voy a pasar por todos ellos ahora mismo. Normalmente iría, pero digamos que de cero a 20MS igual a 5.2020. Entonces, de cero a, ¿qué podría ser en total? Como 60MS, dado la diferencia en cosas. Entonces, más o menos, ¿verdad? No necesitamos ser precisos. Y entonces, simplemente paso por la grabación de esta manera y recojo todos los componentes que se están renderizando. Y una vez que termino con esto, simplemente miro los componentes más costosos aquí, que hasta ahora tengo el editor de widgets y la tabla, y empiezan a tratar de averiguar cómo resolver esto, cómo evitar que esto se renderice.

Entonces, lo que hemos pasado en la última hora fue la demostración, básicamente, del proceso de cómo abordo cómo podrías abordar debugging problemas reales complejos en aplicaciones reales, tomando la aplicación, perfilándola en Chrome Dev Tools, averiguando las partes más costosas y a qué atribuyen a React Rendering, React Effects, otros JS. Luego, si es React Rendering, yendo al React Profiler y encontrando los componentes más costosos. Y luego, una vez que conoces los componentes más costosos, mirando estos componentes en particular e intentando averiguar por qué exactamente se están renderizando y cómo podríamos hacerlos más baratos o cómo podríamos renderizarlos menos a menudo o renderizar menos de ellos o no renderizarlos en absoluto o tal vez hacerlos más baratos. Entonces, en este caso, voy a echar un vistazo... Echemos un vistazo al componente Widgets Editor, que tardó 84 milisegundos en renderizarse. Entonces, voy a ir a Chrome y también saldré de la vista de pantalla completa aquí. Voy a Chrome y voy a llegar a los componentes del editor de widgets y ver por qué se renderizó. Entonces, si hago clic en este componente, si cambio entre los renderizados, veo que la primera vez que el editor de widgets se renderizó fue porque su hook 5 y 47 cambiaron. La segunda vez que se renderizó fue porque su hook número cinco cambió. Y entonces, en este punto, lo que podría hacer o lo que podría hacer es ir a la code base y mirar este widget e intentar encontrar estos hooks, hooks número cinco y hook número 47 que era el componente del editor de widgets. Pero si miro los hooks que tiene este componente, me daría cuenta de que este componente no tiene 47 hooks. Este componente tiene hook, uno, dos, tres, cuatro, cinco, seis, siete, ocho, nueve, 10, 11, 12, 13 y entonces sí, número de hooks. Entonces, el componente tiene 13 hooks. Mientras que DevTools me dice que el hook número cinco y el hook número 47 han cambiado. ¿Alguien sabe por qué está pasando esto? ¿Por qué DevTools me habla del hook número 47? ¿Qué es el hook número 47? Sí, como dice Frederick en el chat, los hooks pueden tener hooks. Y de hecho, como Rack Profiler, Rack Profiler no tiene idea sobre los hooks personalizados que utilizas. Rack Profiler solo tiene visibilidad en los hooks propios de Rack. Entonces, por ejemplo, si tienes algún hook que dice que const, lo sé.

Identificación de Hooks Cambiantes y Optimización de Renders

Short description:

Const useMyHook es similar a useState y luego otro useState. Rack DevTools muestra que el hook número uno y el hook número dos cambiaron. Hay dos formas de identificar los hooks que cambian: cambiar al panel de componentes y observar los números de los hooks o usar la herramienta 'why did you render'. La herramienta realiza un seguimiento de los cambios y renders de los hooks, proporcionando detalles adicionales. Habilita la herramienta para el componente específico para ver por qué se renderizó y qué hooks cambiaron. Los registros muestran los hooks cambiados y las diferencias entre objetos. Esta interacción ayuda a optimizar el rendimiento de la aplicación identificando renders innecesarios.

Const useMyHook es similar a useState y luego otro useState. Y si todos los useMyHook y en algún momento, ambos de estos estados cambian, Rack te mostrará que el hook número uno y el hook número dos cambiaron sin importar dónde, como si ignorara el hecho de que este es el primero, como para el componente de widgets data, este es el único hook que llama. Entonces, Rack DevTools no tiene idea de que tenemos esta función intermedia, la función intermedia useMyHook. Lo único que Rack DevTools sabe son los hooks propios de React. Entonces, cuando tienes esto, ¿cómo sabes exactamente qué hooks están cambiando cuando ves estos números de hooks? Hay dos formas de hacerlo. La primera forma es cambiar al panel de componentes. Vamos a tomar este componente, hacer clic en este componente y luego cambiar al panel de componentes, lo cual funcionará ahora porque la página se recargó pero probablemente no funcionará ahora. Así que voy a volver a grabar la traza porque estoy haciendo cambios en el archivo y la página se recargó. Voy a volver a grabar la traza, abrir. Espera, no. Abrir, grabar, cerrar, detener. Editor de widgets, los hooks número cinco y número 47 cambiaron, misma imagen, ¿verdad? Entonces, ¿cómo aprendemos a qué hooks corresponde esto? Entonces, la primera forma es cambiar al panel de componentes. Así que haz clic en este componente en el panel del perfilador, cambia al panel de componentes, lo cual va a seleccionar el mismo componente del panel de componentes y luego busca la sección de hooks. A diferencia del panel del perfilador, el panel de componentes sabe sobre los hooks personalizados. Entonces, en este panel verías todos los hooks personalizados que usas en tu aplicación. Y si abres, y tienes estos hooks, verías los hooks de React reales etiquetados con números, que podrías usar para hacer coincidir los, los hooks de los que el perfilador te informa con los hooks personalizados del componente. Entonces, en este caso, tuvimos el hook número cinco y el hook número 47 cambiaron. Así que veamos el hook número cinco. Ok, no, esto no es params, dispatch, store, redux, context, no, solo hay contextos. Selector, redux, contextos, contextos, y select, aha. El hook número cinco parece ser el primer hook de selector utilizado. El hook número 47 parece estar en algún lugar aquí al final. Oh sí, aquí está el hook número 47 es un useEffect dentro de dynamic app layout. Genial. Entonces, la primera forma de averiguar por qué exactamente se renderizó el, o qué exactamente son estos hooks, la primera forma que uso es cambiar al panel de componentes y observar estos números. Eso funciona, a veces es un poco ruidoso porque muestra que la función useEffect cambió, lo cual realmente no me importa en cuanto al rendimiento. Esa función puede cambiar tanto como quiera. Pero hay otra forma que a veces uso. La segunda forma que uso y que realmente me gusta es una herramienta llamada 'why did you render'. Esta herramienta, wow, ves que acaban de hacer el encabezado blanco. Eso acaba de suceder literalmente. No estaba así el día anterior. Estoy asombrado. Entonces, 'why did you render' es la herramienta que acaban de dejar en el chat. Es una herramienta que agregas a tu aplicación así y lo que hace es parchear React, anula todos los hooks y rastrea los cambios de los hooks, rastrea cuando cualquier componente o cualquier hook cambia y causa que algo se renderice. Por defecto, si especificas el código así, esta aplicación va a intentar rastrear, esta biblioteca va a rastrear todos los componentes puros y registrar todos los componentes puros. La forma en que me gusta usarlo es un poco diferente. Lo que me gusta usar es habilitarlo para un componente específico. Y así es como lo voy a hacer. Primero voy a ir a s3c / index.JSX y voy a habilitar 'why did you render' en sí mismo. Ya lo tengo configurado también configurado para el hook de selector de usuario para el personalizado para registrar específicamente el selector. Y lo segundo que voy a hacer es ir al editor de widgets y voy a establecer widgets editor. why did you render igual a true. ¿O incluso mejor, por qué renderizar locks en diferentes valores igual a true? Así que simplemente establecer true va a advertirte solo sobre renders innecesarios cuando nada cambie. Lock en diferentes valores te va a decir sobre cada render que ocurra. Así que veamos qué tengo ahora. Ahora, si cada vez que se renderiza el editor de widgets, voy a obtener registros en la consola que me dirán por qué exactamente se renderizó este editor de widgets. Espera, déjame filtrar los registros de Web Vitals. Entonces, en este caso, puedes ver que cuando hice clic en el input, el editor de widgets se renderizó dos veces. Y ambos de estos renders ocurrieron debido a cambios en los hooks. Y muestra qué hooks exactamente han cambiado, qué use selector, esto puede ser el mismo use selector, esto puede ser selectores diferentes, es difícil decirlo desde esto, pero muestra qué objetos concretos dentro de los use selectors han cambiado. Y también muestra la diferencia entre estos objetos. Hasta ahora, esta es la interacción que realmente no me importa, tal vez lo aborde más adelante cuando profundice en la optimización de las partes de la aplicación. Pero por ahora, la única interacción que me importa es esta. Y simplemente hago clic en el desplegable y obtengo tres registros o dos renders del editor de widgets. Sinceramente, no sé la lógica de agrupación concreta que utiliza cuándo exactamente agrupa. Entonces, el número de registros aquí no corresponde realmente al número de renders. Pero la razón por la que los registros son lo que siempre estoy mirando. Y si miro estas cosas, los registros, puedo ver que el primer cambio que ocurrió, el primer cambio que ocurrió en el editor de widgets es este hook de use selector. Y el use selector devuelve objetos diferentes que son iguales por valor. Lo cual es un patrón común en cuanto al rendimiento cuando tienes un use selector que devuelve lo mismo como objetos que se ven iguales, tienen los mismos campos, tienen los mismos datos, tienen los mismos valores, pero las referencias de los objetos no son iguales. Entonces, los objetos, los objetos no son estrictamente iguales. Y lo que me dice de inmediato es que algunos use selector devuelve objetos diferentes que son iguales por valor. Luego, otro use selector también devuelve objetos diferentes que son iguales por valor. Y finalmente, algún tercer use selector, que puede ser el mismo o no. También devuelve objetos diferentes que son iguales por valor. Y puedo ver los valores. Puedo ver, ok, este es un use selector que tiene datos que se ven así. Y este es un use selector que tiene datos que se ven así, cuyo nombre, cuyo nombre. Y cosas similares aquí.

Depuración con 'why did you render'

Short description:

La herramienta 'why did you render' ayuda a identificar no solo los hooks que cambiaron, sino también los valores y cómo cambiaron. Proporciona información sobre cambios necesarios e innecesarios. Sin embargo, no reemplaza al React Profiler, que muestra qué hooks cambiaron pero no cómo cambiaron. Para determinar qué hook está cambiando, utilizo puntos de interrupción condicionales en la biblioteca 'why did you render'. Este enfoque me lleva directamente al código y muestra los cambios exactos en los datos. Tomando notas y analizando las partes más costosas, puedo centrarme en optimizar los selectores y mejorar el rendimiento de la aplicación. Es importante tener en cuenta la experiencia del equipo y la sobrecarga de useCallback y useMemo al decidir si utilizarlos de manera extensiva.

Pref next, qué cosa, esto capturará algo bastante similar. Tal vez esto sea el mismo use selector. Entonces, lo que veo gracias a why did you render no son solo los, no solo los hooks que cambiaron, sino también los valores que cambiaron y cómo exactamente cambiaron esos valores. Y podría ver de inmediato si ese cambio fue necesario porque, por ejemplo, algunos campos reales cambiaron o si ese cambio fue innecesario porque, por ejemplo, algo se renderizó pero el estado de la aplicación en realidad no cambió como si solo hubiera cambiado la referencia del objeto. Y esto probablemente sea un gran candidato para optimización.

Pero ahora, hasta ahora, esto es como, esta herramienta hasta ahora no es realmente, se complementan entre sí, pero no reemplazan al RectorFiler por defecto, ¿verdad? Porque si miras el RectorFiler, RectorFiler, RectorFiler te mostrará que, ok, los hooks número cinco y 47 cambiaron, pero no te mostrará cómo exactamente cambiaron. Si miras why did you render, why did you render te dirá, ok, así es exactamente cómo cambió este hook, pero no te dirá qué, por ejemplo, qué hooks exactamente son estos. Y si tengo múltiples selectores, como aquí, puede ser bastante difícil averiguar qué hooks exactamente son estos. Entonces, lo que también me gusta hacer, para averiguar, para evitar cambiar al perfilador completamente durante un tiempo y trabajar exclusivamente con why did render, lo que también me gusta hacer a veces para averiguar qué hook exactamente está cambiando aquí, es lo siguiente que me gusta hacer. Iría a la línea que parece cualquiera de estos valores, cualquiera de estos logs de tu selector de hook, haría clic en esta línea, lo que me llevaría a la fuente, a la fuente de la biblioteca why did you render que registra la diferencia, ¿verdad? Haría clic con el botón derecho en la línea que hace el log, haría clic en seleccionar en puntos de interrupción condicionales, Y obtendría un punto de interrupción condicional que solo se activará cuando el hook en el que estoy interesado realmente cambie, que va a ser el hook. Voy a ejecutar hook name igual a tu selector. Y tal vez, ¿qué tal si agregamos alguna otra condición también, porque los tres, los tres son tus selectores. ¿Qué tal si agregamos widget name? Como que el siguiente objeto debería tener un campo de nombre de widget. Porque este no lo tiene, este está estructurado de manera diferente. Entonces, fuentes, ¿puedo encontrar la cadena de pase, el valor de preparación, siguiente y siguiente valor. Sí. Entonces puedo usar editar punto de interrupción, tu selector y siguiente donde debería existir tu nombre de widget. Entonces, ahora si agrego este punto de interrupción condicional, el punto de interrupción que solo se detendrá cuando la condición sea verdadera. Y si intento repetir mi interacción, en el momento en que el selector en el que estaba interesado cambia, obtendría estos logs. Ves que estos logs comenzaron a suceder, se detuvieron a mitad de camino. Pero también obtendría un punto de interrupción. Y luego, si desde ese punto de interrupción, miro la pila de llamadas, y voy varias capas más arriba hasta llegar a mi propia aplicación code, llegaría a la línea exacta, el selector exacto que selecciona los data y el selector exacto que cambia con la precisión del 100%, a menos que los mapas de origen estén desactivados o algo así. Y este es el enfoque que realmente, realmente me gusta porque no requiere que cuente los números como en el panel de componentes, me lleva directamente al código, y también muestra los cambios exactos en los datos. Entonces veo los hooks que están cambiando y veo cómo exactamente están cambiando, y eso realmente ayuda en la debugging. Y así, lo que seguiría haciendo en este caso es seguir... Volvería a mi diagrama de flujo y seguiría tomando notas. Entonces, digamos, estamos debugging el editor de widgets, ¿verdad? Entonces, el editor de widgets se renderiza porque los hooks número cinco y 47 cambiaron, lo que sean estos hooks. Entonces, el perfilador dice que los hooks número cinco y 47 cambiaron por primera vez, ¿verdad? Y luego solo el hook número cinco cambió en la segunda renderización. Hmm, entonces, como en la primera renderización, los hooks número cinco y 47, ¿verdad?, en la segunda renderización solo el hook número cinco. Y lo que why did you render me dice es que el primer hook que cambió fue el widgetsUseSelector. Sí, fue el widgets use selector. Ok. Y eso fue un cambio innecesario porque los objetos se mantuvieron iguales. Además, el hook número siete era algún otro use selector, que debug. Y luego el tercer selector también era algún otro use selector, tal vez el mismo use selector, porque mira, hook número cinco, hook número cinco. Y la forma de los datos del primer hook y el tercer hook es muy similar. Tal vez sean el mismo hook, podría confirmarlo estableciendo los puntos de interrupción o simplemente podría asumirlo y verificarlo más tarde, además del widgets use selector, que también fue innecesario. Pero es como con un signo de interrogación porque aún no lo he verificado estableciendo los puntos de interrupción. Y así hago estas notas y averiguo, así que acabo de averiguar dónde está el componente para la renderización. Y luego, a partir de aquí, solo iría y haría algunas, como averiguar por qué estos selectores están cambiando y tal vez hacer algunas optimizaciones específicas del selector, algunas optimizaciones de redux. Esto no es, nuevamente, no es el tema de este workshop, pero sí, no sé. Tal vez podría optimizar el selector. Tal vez podría agregar alguna calidad más profunda aquí, pasar el segundo parámetro a tu selector. Tal vez podría refactorizar el selector. Cosas así. Pero así es como te acercas, así es como realmente me acerco a debugging una aplicación del mundo real grande y compleja. Tomo muchas notas y también voy de arriba a abajo averiguando las partes más costosas. Pero con notas y sabiendo las partes más costosas, generalmente puedo enfocar mis esfuerzos en las partes correctas y realizar cambios reales. Así que veo algunas preguntas en el chat. Lucas pregunta, ¿hay algo más que el editor de widgets que why did you render true para que esto funcione, no puedo hacer que funcione por alguna razón. Entonces, el cambio que hice fue en realidad el editor de widgets, ¿por qué did you render lock en diferentes valores true? Lo que hace que se bloquee en cada renderización. Pero, oh, lo siento. Creo que por qué no funciona para ti si estás siguiendo los cambios desde la aplicación, por qué probablemente no funcione para ti, ¿has descomentado esta línea en index.js? Porque también necesitas... No, eso sería todo. Gracias. Genial. Excelente. Muy bien. ¿Alguna otra pregunta sobre lo que hemos visto hasta ahora? Muy bien. Veo algunas preguntas en el chat. ¿En tu día a día, usarías useCallback, UseMemo en todas partes antes de la optimización? Ooh. Esa es una gran pregunta. Y no tengo una respuesta sí o no. Creo que depende en su mayoría del equipo con el que trabajo. Idealmente, si todos los ingenieros con los que trabajo son súper experimentados con React y conocen muy bien, como dónde necesitan optimizar, no lo haría. Por dos razones. Primero, useCallback, UseMemo es una sobrecarga, una sobrecarga de CPU. Como cada vez que necesitas, cada vez que el componente renderiza useCallback y UseMemo tienen que comparar las dependencias, ¿verdad? Y eso es barato, pero eso es como en su aplicación. Y por las dependencias, ¿verdad?, solo estoy hablando de... Dame algo. Dame algo.

Optimización de código y efectos en React

Short description:

En un equipo senior, es recomendable evitar el uso de useCallback y useMemo de forma predeterminada debido a sus costos de rendimiento y aumento del uso de memoria. Sin embargo, en un equipo de nivel medio, utilizar useCallback y useMemo como regla general puede mejorar el rendimiento. El hook useWhyDidYouUpdate es una solución de complemento ligera que ayuda a identificar qué valores están cambiando en un componente. Proporciona información sobre renders innecesarios y puede ser una herramienta útil para la optimización. Al optimizar los renders de React, herramientas como el React Profiler, useWhyDidYouUpdate y puntos de interrupción condicionales pueden ayudar a identificar y solucionar problemas de rendimiento. La rama de efectos del FlameChart se centra en optimizar el código de React que ejecuta efectos, en lugar de código relacionado con los renders. Esto requiere diferentes herramientas y técnicas para identificar y resolver problemas de rendimiento. Por ejemplo, analizar estadísticas de renderizado de frames puede ayudar a identificar interacciones lentas en una aplicación.

Entonces, ¿así es como funciona? Cada vez que este componente se renderiza, useCallback tiene que comparar estas dos propiedades y con un montón de useCallbacks y UseMemos en la aplicación. Así que ahí está la primera razón. La segunda razón es que también, como, aumenta el uso de memoria. Un amigo mío va a hablar de esto en React Day Berlin, si su charla es aceptada. Pero espero mucho que la charla sea aceptada porque va a hablar sobre el uso de memoria, como cuánta memoria realmente usa useMemo. Pero la idea es que, si, para comparar los valores anteriores con los valores siguientes, React tiene que almacenar la forma anterior de verano. Y eso aumenta el uso de memoria de las aplicaciones. El recolector de basura no puede liberar estos valores incluso si ya no son realmente necesarios. Entonces mi pregunta es, en un equipo muy experimentado, probablemente evitaría usar useCallback y useMemo de forma predeterminada. Porque eso no es gratuito. Ooh, wow. ¿Es ese un enlace real? Wow. Eso es un enlace real. Debería sobornar a alguien en GitHub para que recomiende mi contenido. Pero esto es en realidad un buen artículo sobre los costos de rendimiento de useCallback y useMemo. Así que voy a dejarlo en el chat. Ok, no, esto va a quitarme el trabajo en algún momento, definitivamente. Pero en un equipo de nivel medio, probablemente usaría useCallback y useMemo de forma predeterminada simplemente porque si las personas no tienen una experiencia profunda con React, usar useCallback y useMemo como regla general, sin necesidad de pensarlo, simplemente aplicarlo de forma predeterminada, probablemente traerá más beneficios de rendimiento que los costos que conllevaría. Así que creo que depende del nivel del equipo.

Ok, Frederick pregunta si why did you render afecta el rendimiento de React en producción, ya que parece que se extiende mucho. Sí, lo hace mucho. No he medido los cambios exactos, pero creo que vi, ya sabes, cuando mides cosas sin why did you render, luego agregas why did you render y vuelves a medir, creo que se vuelve como un 30 o 50% más lento. Así que nunca quieres habilitarlo en producción, solo quieres habilitarlo en desarrollo y el ejemplo de código se encarga de esto. Frederick pregunta, a veces uso un hook, why did you update, ¿alguna idea al respecto? Sí, voy a mostrar esto. No, creo que no voy a mostrar esto, no vamos a tener suficiente tiempo para esto, pero sí, hay un gran hook llamado useWhyDidYouUpdate. UseWhyDidYouUpdate, existe en varias bibliotecas, incluyendo hooks, realmente me gusta la versión de él que se puede copiar y pegar. Así que, como el sitio web de usehooks solía tener esta función hasta la reciente rediseño, ahora ya no lo tienen por alguna razón, simplemente redirige a alguna otra función que es completamente diferente, ya sabes. Pero lo guardé en un gist y voy a compartir las diapositivas después. Así que estos enlaces serán clicables. Y si haces clic en este enlace de useWhyDidYouUpdate, obtendrás un gist que es básicamente una versión copiable del hook useWhyDidYouUpdate. Y lo que hace este hook es simplemente mostrarte logs en la consola y algunas props que le pasas o algunas construcciones que le pasas, cambian. Y me gusta usar esto como una solución de complemento realmente ligera porque me gusta mucho que se pueda copiar y pegar, no necesito instalar nada, no necesito reiniciar mi servidor ni nada. Solo puedo copiar el hook, pegarlo en los componentes y luego usarlo para decirme qué valores están cambiando exactamente. Espera, déjame hacerlo compatible con TypeScript. Sí. Bueno, un tipo realmente malo todavía. Así que veamos cómo podría ayudar aquí. Así que recuerda cómo estábamos tratando de averiguar qué hooks estaban cambiando, ¿verdad?, y estábamos agregando puntos de interrupción y solo estábamos mirando los valores. Estábamos mirando el estado de la llamada para averiguar qué selectores están cambiando realmente. Otra forma de averiguar qué hooks están cambiando es simplemente usar esta función, useWhyDidYouUpdate, que puedes encontrar buscando en Google o la encontrarás en mis diapositivas, en esta diapositiva que compartiré en Discord. La forma en que funciona useWhyDidYouUpdate es que llamas al hook, pasas el nombre del componente o básicamente cualquier cadena que desees. Así que voy a llamar a esto, que es editorSelectors. Y luego pasas las dependencias que deseas observar. Canónicamente, típicamente son las props, y de manera monótona, la forma en que usarás esto, pasarás el nombre del componente y pasarás las props y la función te mostrará un log cuando cualquiera de las props cambie. Pero me gusta usarlo para fines no canónicos porque con las props ya puedo usar DevTools, pero para averiguar qué selector ha cambiado, bueno, ninguna de las herramientas es buena para esto. Así que en este caso, para averiguar qué selector ha cambiado, podría llamar a useWhyDidYouUpdate, pasar cualquier cadena que se mostrará en la consola y pasar los valores que quiero observar. Y luego, cada vez que alguno de estos valores cambie o, lo siento, cualquier cosa de los valores que pasé al componente cambie, obtendría el log de qué valor exactamente ha cambiado y también cuál era el valor anterior y cuál era el valor siguiente. Y eso es quizás la forma más fácil, la más liviana de averiguar qué hooks, qué valores en tu componente han cambiado realmente. Aquí puedo ver de inmediato que, ok, pasé cinco selectores, un selector cambió de este valor a este valor, esto significa que debería centrarme en este selector e intentar optimizarlo. Así que eso es, gracias. Esa es una gran pregunta. Y sí, me gusta mucho usar esta herramienta, es genial.

De acuerdo, ¿alguna otra pregunta sobre lo que hemos visto hasta ahora antes de echar un vistazo a la rama de efectos del FlameChart? Echemos un vistazo a los efectos. Hasta ahora, nos hemos centrado principalmente en los renders de React porque, típicamente, a menudo, esa es la parte más costosa. Entonces necesitas aplicar un montón de herramientas, un montón de técnicas para optimizar esto. Así que lo que hemos hecho hasta ahora es tomar la aplicación simple primero y luego tomar la aplicación del mundo real más tarde, ¿verdad? Y grabamos la interacción usando DevTools. Analizamos cada parte de la grabación de DevTools. Vimos que la mayor parte del tiempo se gasta en el render de React. Así que cambiamos al React Profiler y grabamos la traza con el React Profiler y descubrimos los componentes más costosos. Y luego intentamos responder por qué estos componentes se estaban renderizando. Y usamos la casilla de verificación de grabar componentes que se renderizan. En DevTools, usamos useWhyDidYouUpdate, usamos puntos de interrupción condicionales. Estas son todas las herramientas que se utilizan regularmente para resolver problemas. Pero ¿qué sucede si haces una grabación y en lugar de que el renderizado sea la parte más costosa del código, es algún código de React, pero el código de React que ejecuta efectos? Echemos un vistazo. Aquí hay otra interacción que es lenta. Y notamos que es lenta tal vez porque los usuarios se quejaron de eso, tal vez porque lo notamos. Pero digamos que los usuarios se quejaron de que cada vez que abren las propiedades del widget de cualquier widget, la aplicación se retrasa un poco. Y nuevamente, no podrás ver esto porque estoy compartiendo pantalla, pero voy a habilitar las estadísticas de renderizado de frames y puedes usar las estadísticas de renderizado de frames para ver cuándo se retrasa la aplicación. Hasta ahora, la aplicación es bastante fluida, solo estoy pasando el cursor por encima.

Análisis del rendimiento de la aplicación y ejecución de funciones

Short description:

Para depurar el lento rendimiento de la aplicación, comienza grabando la interacción utilizando DevTools. Busca picos en la actividad de la CPU, acércate al pico relevante y analiza las funciones que se están ejecutando. Anota las diferentes partes de la grabación para identificar renders y efectos costosos. Presta atención al tiempo invertido en la función de commit de efectos de diseño y en el proceso de recalculación de pilas. Aunque las recalculaciones de estilo están fuera del alcance de esta masterclass, hay recursos disponibles para aprender más sobre ellas. La segunda parte del análisis se centra en otro RectRender, los efectos de diseño de commit, los efectos pasivos de flash y las microtareas de ejecución. Anota estas partes para entender el tiempo invertido en renders y efectos. Utiliza las anotaciones para guiar el perfilado y la depuración de los problemas de rendimiento de la aplicación.

Pero ahora si abro cualquier, si hago clic en cualquier componente, que también abre su panel de widgets, verías cómo la aplicación simplemente se congela durante un período de tiempo realmente largo, ¿verdad? Mira, eso es de nuevo, como que era una barra de hilos realmente gruesa aquí de nuevo. Así que esto significa que la aplicación era bastante lenta. ¿Cómo lo depuramos? Para depurar esto, el primer paso que siempre tomo es tomar la interacción y grabar la dirección utilizando DevTools. Así que cierro el desplegable y abro el desplegable o abro el panel de propiedades, lo que sea, y hago clic en detener la grabación. Y luego miro la grabación, veo dos picos. Lo primero que miro es la fila de la CPU y veo dos picos de actividad de la CPU, uno cuando cierro el desplegable y el segundo cuando abro el desplegable. Y este es el pico que me importa así que voy a acercarme a él. Y si me acerco, si miro el pico y si sigo pasando por la grabación principal, analizándola de la misma manera que la estábamos analizando aquí, notaría que la mayor parte del tiempo aquí se pasa ejecutando la función de commit de efectos de diseño. Así que veamos, hagamos en realidad la misma cosa de scrinching, ¿deberíamos? ¿Qué es más rápido en este caso? Así que tomé una captura de pantalla, voy a crear un nuevo rectángulo o lo que sea. No, por favor haz clic, haz clic, no, no, arruiné todo. Bien. No voy a crear un rectángulo. Voy a pegar las capturas de pantalla y simplemente voy a anotar las partes de ella. Así que hagamos eso rápidamente, ¿deberíamos? La primera parte 34 milisegundos, Watch Sync Callbacks, PerformSynchronicRouteRoot, RenderRootSync. Tenemos algo de renderizado de React que toma 30 milisegundos. También están las partes divertidas, que no vamos a cubrir en esta masterclass, es que la mayor parte del tiempo aquí más abajo se pasa recalculando pilas. Así que tenemos algunos componentes costosos o tenemos algún render costoso. Pero la mayor parte del tiempo aquí se pasa no ejecutando JavaScript, sino ejecutando código de cálculo específico del navegador que está fuera del alcance de esta masterclass. Así que simplemente voy a oops, resaltar esto así y sin relleno y decir que debería ser violeta. Hagámoslo violeta y digamos que, bien, esto es el renderizado de React, pero con la mayor parte de su tiempo gastado recalculando, ejecutando un recall de estilo. Y sé que es un recall de estilo porque veo ese rectángulo violeta aquí y también este rectángulo dice recalcular estilo. Así que, bien, es un recall de estilo. Y como mencioné, esto está fuera del alcance de esta masterclass, pero hay una rama aquí para esto con el primer enlace que podría comenzar desde para aprender más sobre esto, mostrando todos los diferentes estilos que puedes ejecutar en el estilo. Mostrando todos los, como diciendo más, contándote más sobre este problema y mostrando todas las propiedades que van con esto. Así que si te encuentras con esto, espero que esto ayude o también podrías venir a la gran masterclass que voy a dar pronto y aprender. Oh, en realidad, no, lo siento, no vamos a cubrir eso allí. Así que no vengas allí para los recalls de estilo. No vamos a cubrir eso allí. Así que esa es la primera parte.

La segunda parte, veamos, obtenemos otro RectRender, que toma 74 milisegundos. Así que voy a resaltar eso con verde. Así que esto es RecTrender. Simplemente voy a usar los mismos colores y no poner ninguna etiqueta. Luego obtenemos los efectos de diseño de commit que toman 600 milisegundos. Y era rojo. Luego obtenemos algunos efectos pasivos de flash, más efectos. Así que voy a extender esto un poco. ¿Puedo hacerlo? No, OK, solo puede moverse de una manera. Se ancla a la cuadrícula. Y obtenemos otro renderizado de React. Render root sync 64 milisegundos. Así que, bien, esto es verde. La mayor parte de esto aquí es verde. Luego obtenemos algunos efectos pasivos de flash, algunos efectos menores. Ni siquiera voy a cargarlos. No lo estoy haciendo en este punto porque son solo siete milisegundos. Y luego obtenemos algunas microtareas de ejecución. Cosas de ejecución de microtareas. Y, oh, la misma imagen que vimos durante la sesión de perfilado anterior. ¿Reconoces esto? Render root sync commit root. Render root sync commit root. Efecto de renderizado. Efecto de renderizado. Lo mismo que vimos aquí. Así que lo mismo está sucediendo allí. Así que simplemente voy a tratar de copiar estos. Y no, OK, no, esta herramienta realmente no es conveniente para las anotaciones. Simplemente voy a etiquetar esto como renders y efectos. Y va a ser verde porque son en su mayoría renders. Así que una vez que anoto todo esto, voy a notar que la mayor parte del tiempo aquí se pasa en efecto. Y entonces voy a ir a la camisa de llama. Y voy a ir al nombre, al siguiente rectángulo, que me dice cómo perfilar esto a continuación. Pero la parte de anotación es realmente, realmente importante. Porque si no hago la anotación, si no miro a través de los nombres de las funciones de React, si no averiguo si es un render o un paso de efecto, lo que puedo hacer, lo que podría suceder es que miraría este código. Notaría que la mayoría de las cosas que suceden aquí son un renderizado de React. Y entonces cambiaría al profiler. Ejecutaría un renderizado de React que no quiere ejecutarse. Spew fork slowdown profiler. Yo ejecutaría.

Análisis de Efectos y Optimización del Rendimiento

Short description:

Al analizar los efectos en el perfilador de React, es importante notar que solo muestra los renders y no muestra los efectos ni su costo. Para optimizar los efectos, es necesario ir más abajo en el rastro y examinar los efectos reales llamados por React. Al analizar los efectos, es posible identificar cuáles se están llamando y por qué son costosos. En el ejemplo dado, hay ocho efectos, cuatro de los cuales pertenecen a componentes estilizados. Dado que los componentes estilizados funcionan de manera diferente en desarrollo y producción, no son una preocupación para la optimización. En cambio, concéntrate en los efectos que se están ejecutando y comprende lo que está sucediendo dentro de ellos. En el caso de los efectos del componente did mount, no es posible hacer que se ejecuten con menos frecuencia. Sin embargo, vale la pena examinar el código dentro de los efectos para identificar cualquier optimización potencial. Al analizar el código, puede ser posible hacer que los efectos sean más baratos y mejorar el rendimiento general.

Entonces notaría que la mayoría del code en el rastro es el renderizado de React. Oh, lo siento. Notaría que lo que podría suceder, si no hago esa anotación, es que notaría que la mayoría del código en el rastro es React. Entonces cambiaría al perfilador de React, y grabaría un rastro. Y miraría el rastro. Y vería algún renderizado costoso, y trataría de optimizar este renderizado. Vería que, OK, este componente es costoso, y este componente es costoso. Pero podría perder totalmente que el renderizado aquí toma solo 43 milisegundos. Y mientras que los efectos toman literalmente 10 veces más tiempo. React, las React DevTools ahora muestran esto para las aplicaciones de React 18. Pero si todavía tienes React 17, no vas a ver esta pista en absoluto. Así que podrías perder esto por completo. Y el perfilador de React no muestra los efectos en absoluto. Lo que veo aquí es que solo veo los renders que han sucedido. No veo ninguno de los efectos. Y no veo qué fue exactamente costoso. Entonces, si solo me enfoco en el perfilador de React, voy a estar equivocado porque voy a estar optimizando la cosa equivocada, lo cual es por qué hacemos todo este resaltado.

Entonces, ¿qué hago? ¿Qué hago una vez que he resaltado y una vez que he descubierto que el fragmento más significativo del code se gasta ejecutando los Efectos de React? Sigo adelante e intento averiguar ¿cuáles son los efectos más costosos? Y luego intento averiguar, ¿por qué se vuelven a ejecutar estos efectos? Y luego intento averiguar, ¿cómo puedo llamarlos con menos frecuencia o hacerlos más baratos? Entonces veamos el conjunto de efectos que estamos ejecutando. Hago clic en grabar, hago clic en este componente que abre su panel de propiedades. Me acerco al evento de clic. Ooh, obtengo la devolución de llamada de la función de nuevo. Ooh, obtengo la devolución de llamada de la función de nuevo, que oculta, oscurece algunas de las cosas que están sucediendo aquí. Esto es muy molesto. Déjame grabar eso de nuevo. Y también fijar esto a la derecha. Así que graba. Abre, para. OK, sí, ahora se ha ido. Entonces obtengo este efecto de 614 milisegundos. Y ahora no puedo usar el perfilador directo más. Lo que necesito hacer es que necesito ir más abajo en el rastro, ir todo el camino hacia abajo hasta que el code de React termine. Y necesito mirar los efectos reales que react llama e intentar ver cuáles de ellos se están llamando y cuáles de ellos son costosos y por qué son tan costosos. Así que hagamos esto aquí rápidamente. Tenemos la llamada commitLayoutFX. Vemos que llama a commitLayoutFX begin something complete, commitLayoutFX on Fibre. Todas son funciones de desarrollo de React DOM. Y luego, OK, obtengo más desarrollo de React DOM. Luego, en algún momento, empiezo a obtener funciones de diferentes componentes, de diferentes archivos, no de React sino de styled components, que es esta función anónima, o componente didMount de myindex.s6 de Kot Editor slash index.s6. De nuevo, styled components, componente didMount de Kot Editor index.t6. Styled components, componente didMount. Styled components, componente didMount. Está bien. Así que esto es bastante interesante. Tenemos ocho efectos. Cuatro de ellos pertenecen a styled components. Así que no estoy seguro de si puedo optimizar esto ahora mismo. Así que yo, siendo la persona de perfilado, me digo a mí mismo, no estoy seguro de que pueda optimizar esto ahora mismo. Pero yo, siendo la persona de la masterclass, voy a decirte que lo que ves aquí es en realidad, no necesitas preocuparte por esto porque los styled components funcionan de manera muy diferente entre el desarrollo y la producción. Y en producción, van a ser mucho más rápidos. Así que no vamos a tener este cuello de botella. Pero volviendo a mí, la persona de perfilado, voy a ignorar los styled components por ahora, y voy a mirar los efectos que estoy ejecutando y simplemente tratar de averiguar qué está pasando aquí. Entonces veo que tengo 4 componentes did mounts del mismo componente, lo que supongo significa que tenemos 4 instancias de los componentes. Si hago clic en esto, podría ver todo el code que sucede aquí. Estamos creando algunas opciones. Estamos creando y estamos llamando a CodeMiro desde TextEditor. Estamos creando un editor de code. Estamos añadiendo un montón de devoluciones de llamada de eventos. Luego estamos llamando a getInputValue. Estamos estableciendo el valor. Estamos llamando a updateMarkings, y estamos llamando a startToToComplete. Así que en este punto, voy a preguntar a mí mismo una de dos preguntas. Primero, ¿puedo hacer que este efecto se ejecute con menos frecuencia? ¿O puedo hacerlo más barato? Cualquiera de las dos me va a ayudar a optimizar este componente. Entonces, primero, ¿puedo hacer que este efecto se ejecute con menos frecuencia? No creo que pueda porque es un componente que se monta. Siempre se activa cuando se monta el componente. Así que realmente no puedo hacer nada con él. Así que no, no puedo. ¿Pero puedo hacerlo más barato? Entonces, para responder a esto, simplemente voy a volver a DevTools y voy a mirar todo lo que sucede durante la llamada del componente de desmontaje. Y voy a tratar de averiguar cómo optimizar eso. Así que en este caso, puedo ver que la llamada al exterior del frente toma más de la mitad del costo total de todo el costo. Pero es un code de Codemirror.

Uso de la API ConsoleTime para el perfilado

Short description:

La API ConsoleTime es una API integrada en el navegador que mide la duración del código. Al envolver partes específicas del código con llamadas a console time y console time end, podemos medir sus duraciones. Este enfoque ligero proporciona información sobre el rendimiento de diferentes secciones de código. La API ConsoleTime es útil para perfilar rápidamente el código e identificar partes costosas. Se puede utilizar junto con el panel de rendimiento para grabar rastros y analizar las duraciones de las secciones de código anotadas. Esta herramienta es especialmente útil cuando se trata de aplicaciones grandes y se intenta localizar secciones de código específicas en la grabación.

Entonces, de nuevo, proviene de la biblioteca de terceros. Y tal vez podamos optimizarlo. Tal vez no podamos. Obtengo un par de otras llamadas de Codemirror. Obtengo esta llamada de inicio de la completa, que toma alrededor de un cuarto del tiempo. Y es nuestro code. Y entonces, en este punto, estamos gradualmente pasando del área de debugging al área de solución. ¿Verdad? Así que obtuvimos el concreto. Encontramos el cuello de botella concreto. Y estábamos tratando de averiguar cómo optimizarlo.

Y entonces, en este punto, no voy a ir más allá. Pero quiero mostrar una última herramienta que a menudo es muy útil para el perfilado que a veces uso en lugar de simplemente mirar en DevTools. Esta herramienta es la API ConsoleTime, ConsoleTimeAnd. Y por cierto, tengo curiosidad, gente, para la gente que está aquí, ¿han oído hablar de esta API antes? ¿Han usado esta API antes? ¿Podrían enviar un más al chat si han usado ConsoleTime antes o un menos si no lo han hecho? Más, más, más, más. Menos. Sí. Uh-huh. Bien. Entonces, algunas personas pueden usar, algunas personas no, así que voy a mostrarlo. Bien.

Entonces, la API ConsoleTime es una API de navegador integrada realmente agradable que te permite medir la duración de cualquier pieza de code que quiero perfilar. Entonces digamos que quería. Tengo este componente muy costoso que no está bien en el code editor. Indexado como componente seis en el mío. Y entonces, digamos que estaba revisando esto y estaba tratando de averiguar qué parte de esto es la más costosa. Podría hacer esto grabando un rastro de performance. Pero no siempre es conveniente, es mucho esfuerzo, hace que la aplicación sea más lenta. No sé, a veces solo quiero perfilar algo rápidamente. Además, podría tener un montón de funciones anónimas como estas que son difíciles de atribuir, ¿verdad?

Entonces, una forma de averiguar por qué el modo de componente es costoso es mirar a través de las herramientas de desarrollo, pero otra forma de averiguar por qué es tan costoso es simplemente dividirlo en varias partes y envolver estas partes con llamadas a console time y console time end. Entonces, intentemos hacer eso. Entonces, voy a dividir esto en varias partes y voy a envolver estas partes con console time y llamadas de console time end pasando la misma etiqueta cada vez. Entonces, la primera parte va a ser la parte donde creamos las opciones. Console time, console time, end. La segunda parte va a ser could mirror dot from text area. Console time, console time ends. La tercera parte va a ser could mirror event listeners. Console time, console time ends. Y la cuarta parte va a ser, la primera parte va a ser could mirror dot set calls. Console time and console time ends. Y hagamos un par de las últimas. Por favor, actualice las marcas. Y comienzan a completarse. Entonces, lo que esto va a hacer es que le pedirá al navegador que mida cada duración entre las llamadas de console time y console time end y registre la duración con la etiqueta que pasa en estas llamadas de console. Y eso, a diferencia de la grabación de performance, es muy, muy ligero. Así que puedo ejecutarlo fácilmente sin despachar el navegador completo, tal vez incluso puedo mantenerlo en producción. En realidad, no lo sé. ¿Puedo mantenerlo en producción? Tal vez pueda, si no es un code crítico de performance. Entonces veamos cómo se ve eso. Voy a abrir el performance. Lo siento, abre el panel de widgets. Y voy a mirar los registros. Y en los registros, obtendría de inmediato la dirección, obtendría las duraciones de cada parte de la función que envolví con console time. Entonces puedes ver que esta parte fue barata. Esta parte fue barata. Estas cuatro de estas partes fueron baratas. Mientras que estas partes, estas dos partes fueron costosas. Entonces, probablemente ahora podría repetir lo mismo con, oh, lo siento, estas dos partes fueron costosas. Probablemente ahora podría entrar en este inicio después de completar y como agregar console time y console time aquí ahora y como averiguar, tratar de averiguar qué partes de estas funciones son costosas y luego simplemente seguir hablando y hablando así. Así que podría usar eso. Otra forma en que podría usar esto si tengo muchas cosas en el panel de performance y es difícil para mí encontrar exactamente dónde están sucediendo estas llamadas o exactamente, dónde exactamente está sucediendo el montaje del componente. También podría agregar estas llamadas de montaje del componente. Lo siento. También podría agregar estas llamadas de console time y luego ir al panel de performance y grabar el rastro con las llamadas de console time en los códigos. Y lo que sucederá entonces es que obtendría el área de tiempos que me muestra todas las partes del code que fueron anotadas con ya sea la API de performance mark y performance measure o la API de console time y console time end. Y entonces, si para mí, como si supiera que este componente se monta varias veces a través de la grabación y quiero facilitar para mí encontrar estas llamadas de montaje del componente sin desplazarme por toda la grabación y tratando de averiguar dónde están realmente lo que puedo hacer es que puedo agregar las llamadas de console time o performance mark, performance measure calls y obtendría anotaciones separadas en las herramientas de desarrollo mostrándome cuándo exactamente sucedieron estas llamadas. Y esto es conveniente de usar también en la creación de perfiles de aplicaciones grandes cuando quieres encontrar algo realmente rápido en la grabación completa. Entonces, este es el bit FX. Con FX, lo más importante sobre FX es que con FX, el perfilador no ayuda. El perfilador no te muestra nada sobre los efectos más costosos.

Perfilando Efectos y Preguntas y Respuestas

Short description:

Tienes que usar las herramientas de desarrollo para encontrar las funciones costosas y hacerlas menos costosas o ejecutarlas con menos frecuencia. Usa UseYD ToUpdate, las APIs de console time y console time end, y las APIs de Performance Measure y Performance Mark para identificar y optimizar las partes más costosas de los efectos. Cubrimos el perfilado de una simple aplicación React, resolviendo un problema de escritura, utilizando herramientas como ¿por qué renderizaste? y React DevTools. Para los efectos, usa DevTools y utiliza console time y gate para resaltar las partes de la grabación. Ahora es el momento de las preguntas y respuestas. Siéntete libre de hacer cualquier pregunta o calificar tu comprensión de 0 a 10.

Tienes que usar las herramientas de desarrollo para encontrar las funciones costosas para averiguar dónde estas funciones son costosas y para averiguar cómo hacer estas funciones menos costosas o ejecutarlas con menos frecuencia. Y para hacer eso, podrías usar UseYD ToUpdate, y podrías usar las APIs de console time y console time end, y podrías usar las APIs de Performance Measure y Performance Mark para averiguar por qué se ejecutan los efectos y cuáles partes de los efectos son las más costosas.

Estos son los efectos. Así es como te acercas al perfilado de efectos. Y esto es prácticamente todo para el material de la masterclass de hoy. Me pregunto, gente, si tienen alguna pregunta sobre todo lo que hemos repasado, sobre las cosas que hemos repasado hasta este punto. Sólo para reiterar lo que hemos repasado fue que comenzamos con el perfilado de una simple aplicación de React. Miramos un solo problema, que es escribir en el editor. Descubrimos lo que lo hace costoso usando el perfilador de React. Y lo hemos resuelto. Luego miramos la gran aplicación del mundo real, y usamos más herramientas. Usamos el ¿por qué renderizaste? Usamos las funciones de yd2update. Vimos cómo establecer un punto de interrupción con yd2render para averiguar qué hooks cambian exactamente. Y vimos cómo usamos React DevTools para averiguar qué hooks cambian exactamente. Y con los Efectos de React, aprendimos que no puedes usar el perfilador de React para los efectos. En su lugar, necesitas usar DevTools. Y cuando estás usando DevTools, algunas cosas que ayudan son el console time, y el console time y el gate, que ayuda a resaltar las partes de la grabación.

Así que este es el momento de las preguntas y respuestas. Pregúntame cualquier cosa sobre todo lo que hemos repasado hasta ahora, o pregúntame cualquier otra pregunta general sobre el rendimiento, en general. Y estaré encantado de responder a cualquier cosa. Nos quedan 15 minutos más. Pero también, sólo déjame saber, sólo para entender, ¿podrías poner un número del 0 al 10 en el chat? No la calificación, sino para mostrarme cuánto crees que entiendes de lo claro que fue todo lo que hemos repasado hasta ahora? Como, donde 0 es como, todo fue extremadamente claro, 10 fue como, todo fue extremadamente, realmente claro, el 100% de ello. Así que de 0 a 10, un número en el chat que muestre cuánto crees que entiendes todo lo que hemos repasado hoy. Veo un montón de 9s, 8s, 8s, 8s, está bien. Sí, gente, con 8s o también con 9s, si tienen alguna pregunta concreta, no duden en preguntarme. Y voy a responder a la pregunta de Mayansk sobre cualquier sugerencia sobre actualizaciones del gestor de estado como Redux o Coil.

Optimizando el Gestor de Estado y el Rendimiento de la Memoria

Short description:

Las optimizaciones para el gestor de estado incluyen el uso de Reselect para prevenir la re-renderización del selector y el uso del hook useSelector con una función de comparación de igualdad personalizada. Migrar de Redux a React context puede ser un desafío ya que requiere la reimplantación de las primitivas orientadas al rendimiento de Redux. El rendimiento de la memoria se puede analizar utilizando herramientas como MemLab, que proporciona interfaces personalizadas para medir el uso de memoria del componente. Gracias por asistir a la masterclass.

Entonces, ¿estás preguntando sobre optimizaciones para el gestor de estado, como cómo resolver esto? Sí. Algo así. Como, yo realmente. Lo siento, ¿estoy hablando? Así que va a haber una masterclass más grande que voy a dar a finales de mes que también habla sobre soluciones. No creo que hagamos Redux aquí. Oh, no, hacemos Redux aquí. Sí, vamos a hacer Redux aquí. Como, hay un límite de tiempo. Así que tengo que averiguar qué cortar. OK, entonces vamos a hacer optimizaciones de Redux allí. Así que para dar una respuesta realmente rápida, como hay un montón de cosas que uso. Lo siento, ¿puedo dar una respuesta rápida? Como, si estás buscando algo, lo siento, probablemente no pueda dar una respuesta rápida en la cima de mi mente ahora mismo. Pero es como si tuviéramos como 10 soluciones en esa masterclass. Una de ellas que recuerdo de inmediato, justo en la cima de mi mente es Resellect, que es una biblioteca que ayuda a optimizar algo, para prevenir que algunos componentes, lo siento, para prevenir que algunos selectores se re-rendericen. No lo uso tan a menudo. En realidad, no es como la primera solución a la que recurro. Pero he visto muchas aplicaciones usándolo, es útil. ¿Algo más? Pero no, como la mayoría de las cosas que repasamos en esa masterclass es principalmente como refactorización. Así es como escribimos esos selectores. Así que eso es un poco más lento para mostrar. Otra cosa que puedes usar a veces, también solo para responder a tu pregunta, otra cosa que podrías usar a veces es, use selector. Así que el hook use selector tiene un segundo diferente, lo siento, un segundo parámetro, que te permite especificar la función de comparación de igualdad. Que como por defecto, lo que hace Redux, es simplemente triple igual al valor antiguo y al valor nuevo, ¿verdad? Y si la referencia es diferente, entonces obtendrás una re-renderización. Pero puedes sobrescribir eso pasando la función de igualdad personalizada. Y de nuevo, eso es más de un escape hitch porque si pasas como igual profunda aquí y tus objetos son realmente grandes, eso va a ser más lento que una re-renderización. Como vi una aplicación que es como una igualdad profunda estaba tomando 500 milisegundos o algo así solo sobre dos objetos, eso era mucho. Pero en algunos casos concretos, eso es un buen escape hitch para usar para evitar re-renderizar el componente porque es como para cambiar porque como tal vez la referencia cambió, pero el ID, los IDs no cambiaron el ID producido. Podrías comparar IDs en lugar de hacer triple igual. Así que es cosas así que es respecto a Redux. No tengo ninguna sugerencia de recoil me temo. Bueno, do do do do do do. Nir pregunta si podemos pasar por el enlace de GitHub. Sí, los documentos en los que estamos trabajando están aquí y el enlace de GitHub está aquí. Y también voy a dejar todos los enlaces en el chat de Discord. Así que está aquí, podrías encontrarlo en RS workshops. Más preguntas, Frederick dice que aprendí a distraer el rendimiento de mis aplicaciones al migrar a la nueva aplicación de contexto de moda en su momento. Ahora todo se está renderizando casi en cada actualización, quiero usar el Zeus stunt en el futuro. Ooh bien, lo siento, lo siento que eso sucediera. No tengo ninguna experiencia con el Zeus stunt, espero que ayude en el futuro. Pero en realidad, espera. En realidad estoy curioso, espera, me sorprende que hayas migrado de Redux al contexto de React. ¿Fue eso o hiciste algo más? Sí, más o menos, era una aplicación muy antigua. El antiguo código de Redux, era bastante grande, estos reductores y estas cosas de estado y así sucesivamente. Sí, entonces pensé, está bien, tenemos el contexto de la aplicación, el contexto de React ahora, vamos a hacer proveedores para esto, pero en realidad no fue una buena idea. Mm-mm, sí, lo veo. Sí, supongo... No sé, una cosa sobre... Redux no usa el contexto bajo el capó, ¿verdad? Utiliza un mecanismo diferente, pero no es tan complejo por sí solo. Así que una cosa que es buena de Redux, simplemente te da algunas primitivas que facilitan ser... Bueno, no super fácil, pero más fácil ser rendimiento por defecto. Y entonces cuando cambias de Redux a contexto, básicamente tienes que reimplementar esta primitiva, averiguar las diferentes primitivas desde cero. Y supongo que eso a veces... No confiaría en mí mismo para hacer un buen trabajo en esto. Así que, sí, supongo. Es realmente desafortunado que eso sucediera. Veo cómo eso podría suceder. Quiero decir, todo este código de Redux no usaba reselect o algo así. Así que no sé si lo empeoré, pero ahora está mal. Sí, y supongo que dos estándar o tener diferentes tiendas como esta debería resolverlo. Sí, bueno, espero que ayude. Paulo pregunta sobre el rendimiento de la memoria. Sí, no tengo experiencia con eso, lo siento. Conozco una herramienta, MemLab, que es, así como depurar frentes en dev tools es como, voy a decir que es, lo siento, apesta. Es como las herramientas de memoria de dev tools son muy difíciles de usar. Así que como todas las personas que vi como seriamente haciendo análisis de memoria, normalmente estaban usando MemLab en su lugar. Y también he aprendido recientemente, de nuevo, con el mismo amigo que va a dar una charla en el día de la pista de Berlín, que él como, su charla va a ser sobre reporteros personalizados para el MemLab. Así que podrías envolver, básicamente interfaces personalizadas encima de MemLab y usar eso para mostrar cuánto tiempo, lo siento, cuánta memoria utiliza cada componente, por ejemplo, cuánta memoria como usa la memoria. Y así es como si yo fuera a optimizar la memoria, empezaría desde esto. Muchas gracias por asistir a esta masterclass. Fue un placer presentarte y hablar contigo. Fue un placer, gracias. Espero verte la próxima vez. Sí, preguntas y respuestas hasta que me deslizo. Muchas gracias, adiós.

Watch more workshops on topic

Concurrent Rendering Adventures in React 18
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Top Content
Featured WorkshopFree
Maurice de Beijer
Maurice de Beijer
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Hooks Tips Only the Pros Know
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React, TypeScript, and TDD
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
Paul Everitt
Paul Everitt
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Web3 Workshop - Building Your First Dapp
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Top Content
Featured WorkshopFree
Nader Dabit
Nader Dabit
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
Designing Effective Tests With React Testing Library
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
Josh Justice
Josh Justice
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
Best Practices and Advanced TypeScript Tips for React Developers
React Advanced Conference 2022React Advanced Conference 2022
148 min
Best Practices and Advanced TypeScript Tips for React Developers
Top Content
Featured Workshop
Maurice de Beijer
Maurice de Beijer
Are you a React developer trying to get the most benefits from TypeScript? Then this is the workshop for you.In this interactive workshop, we will start at the basics and examine the pros and cons of different ways you can declare React components using TypeScript. After that we will move to more advanced concepts where we will go beyond the strict setting of TypeScript. You will learn when to use types like any, unknown and never. We will explore the use of type predicates, guards and exhaustive checking. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.

Check out more articles and videos

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

A Guide to React Rendering Behavior
React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
Top Content
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
Building Better Websites with Remix
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Top Content
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
Don't Solve Problems, Eliminate Them
React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Top Content
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
React Compiler - Understanding Idiomatic React (React Forget)
React Advanced Conference 2023React Advanced Conference 2023
33 min
React Compiler - Understanding Idiomatic React (React Forget)
Top Content
React provides a contract to developers- uphold certain rules, and React can efficiently and correctly update the UI. In this talk we'll explore these rules in depth, understanding the reasoning behind them and how they unlock new directions such as automatic memoization. 
Using useEffect Effectively
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Top Content
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
Modern Web Debugging
JSNation 2023JSNation 2023
29 min
Modern Web Debugging
Top Content
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.