Perfile una aplicación React para rendimiento

React DevTools es un software increíble y está disponible como una extensión de navegador para Chrome , Firefox , y puede conectarse para funcionar con la aplicación React en cualquier lugar.

Una de las mejores características de React DevTools es su capacidad de creación de perfiles. Hay mucho en el generador de perfiles, y no vamos a entrar en todo esto en esta publicación, pero pensé que debería mostrarle cómo puede comenzar a usar React Profiler y evitar un escollo común que las personas encuentran al perfilar su aplicaciones.

Voy a trabajar con mi aplicación de estantería que hace un buen trabajo al caminar en la línea entre lo suficientemente práctico como para ser «mundo real» pero lo suficientemente simple como para no requerir una gran cantidad de conocimiento específico de dominio para entender. Siéntase libre de seguirlo si lo desea, o (aún mejor) seguirlo en su propio proyecto.

Instalar la extensión

El primer paso es asegurarse de instalar la extensión React DevTools para el navegador que está utilizando. Estoy usando Chrome, así que lo instalé en Chrome WebStore . Si no aparece después de instalar la extensión, es posible que deba cerrar el panel DevTools de su navegador y volver a abrirlos.

Inicia la aplicación

La aplicación de estantería utiliza react-scripts(gracias a create-react-app), así que después de haber instalado el proyecto localmente, ejecútelo npm run startpara ejecutar el servidor de desarrollo. Esto abrirá la aplicación en su navegador en http://localhost:3000:

aplicación de estantería con botones de inicio de sesión y registro

Comience una sesión de perfilado

Abra las herramientas de desarrollo del navegador haciendo clic derecho en cualquier parte de la página y haciendo clic en «Inspeccionar». Luego seleccione la pestaña «⚛ Profiler». Este es el perfilador React DevTools y ahora puede hacer clic en el pequeño círculo azul para «Comenzar a perfilar» la aplicación.aplicación de estantería con la pestaña React DevTools Profile abierta y el botón azul "Iniciar perfil" resaltado

Desde aquí, adelante e interactúa un poco con la aplicación. Me voy a registrar para una nueva cuenta. Luego haga clic en el pequeño círculo rojo para «Dejar de perfilar».

aplicación de estantería con la pestaña React DevTools Profile abierta y el botón rojo "Stop profile" resaltado

Explore los datos de perfil

Desde aquí, tiene algunas opciones para explorar los datos que las DevTools recopilaron mientras interactuaba con la aplicación. La vista predeterminada es el «gráfico Flamegraph», y también está el «gráfico clasificado». Así es como se ve el «gráfico de Flamegraph»

aplicación de estantería con la pestaña React DevTools Profile que muestra un gráfico de llamas

Peligro: medir el modo de desarrollo

Quiero mencionar un grave obstáculo que debe evitar al realizar mediciones de rendimiento como la creación de perfiles. En este momento estamos midiendo cómo funciona nuestra aplicación en modo de desarrollo. Si ha estado usando React por un tiempo, es probable que sepa que viene con muchas advertencias en tiempo de desarrollo para ayudarlo a alejarse de códigos y prácticas problemáticos. Esta es una de las cosas que más me gusta de React, pero eso tiene un costo de rendimiento (a menudo significativo).

Debido a esto, sus mediciones de rendimiento están contaminadas por el código de tiempo de desarrollo de React (algo que sus usuarios nunca deberían estar ejecutando).

Entonces, si desea obtener una medición precisa del rendimiento de producción de su aplicación, debe asegurarse de realizar sus mediciones en la versión de producción de su código (el código que usarán sus usuarios finales).

Crea y mide la aplicación de producción

Así que ejecutemos la compilación de producción optimizada con npm run build. A continuación, ejecutaremos npx serve -s buildla versión compilada de la aplicación en un servidor HTTP. Eso debería iniciar la aplicación en el puerto 5000. Así que hablemos de eso y comencemos una sesión de creación de perfiles sobre eso … ¡Espere! ¡Oh no! ¿Qué es esto?

Reaccione la pestaña Perfil de DevTools que muestra el error "No se admite la creación de perfiles"

                    Perfiles no admitidos.

                   El soporte de creación de perfiles requiere un desarrollo o una creación de perfiles de producción de React v16.5 +.

Como resultado, React tiene un código específico para la creación de perfiles y con el interés de hacer que su aplicación sea lo más rápida posible, en realidad eliminan ese código de la compilación de producción de React. Gracias reaccionar! Excepto ahora, ¿qué hacemos? Bueno, supongo que podríamos ir a la esencia vinculada por Brian. O podrías seguir leyendo y te mostraré qué hacer.

NOTA: Si está utilizando create-react-app con react-scripts@>=3.2.0, simplemente puede ejecutar npx react-scripts build --profiley hará todo esto por usted ( gracias a Jacob ) y puede pasar al siguiente escollo. De lo contrario, sigue leyendo.

Actualice la configuración del paquete web para perfiles de producción

Como se señaló en el mensaje, hay una versión de producción de React que elimina la mayor parte del código útil del tiempo de desarrollo, pero deja intacto el código de creación de perfiles. Todavía es un poco más lento, pero nos da la mejor idea de cómo están funcionando nuestros componentes en un entorno de producción.

Hay algunas formas de hacerlo, pero la más simple es actualizar la configuración del paquete web para alias cualquier importación de ciertos módulos a la versión de creación de perfiles de ese módulo. Hay dos de estos módulos:

  • react-dom -> react-dom/profiling
  • scheduler/tracing -> scheduler/tracing-profiling

Ambos son paquetes React y necesitan un código especial para que funcione el generador de perfiles.

La forma de actualizar la configuración de su paquete web variará según el marco que esté utilizando (create-react-app, next.js, gatsby.js o el suyo con el paquete web sin formato). En nuestro caso, estamos usando create-react-app y no hay una forma oficialmente admitida de extender o modificar la configuración del paquete web. Afortunadamente para nosotros, esto es solo algo que queremos hacer localmente, así que haremos un poco de espeleología en nuestronode_modules .

Entonces, si está usando react-scripts@3.1.1(o en algún lugar por allí), puede abrir la configuración del paquete web aquí: ./node_modules/react-scripts/config/webpack.config.js

Luego ubique el código que se ve así y agregue las líneas indicadas:

1 // … config …
2 resolver : {
3 // … config …
4 alias: {
5 // Soporte React Native Web
6 // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
7 ‘react-native’ : ‘react-native-web’ ,
8 ‘react-dom $’ : ‘react-dom / profiling’ ,
9 ‘Scheduler / Tracing’ : ‘Scheduler / Tracing-Profiling’ ,
10 },
11 // … más config …
12}
13// … más config …

Perfilar la compilación de perfiles de producción

Genial, ahora corre npm run build, ¡ npx serve -s buildy volvamos a crear un perfil de la aplicación! Seguiré los mismos pasos de registro que hice la última vez. Esto es con lo que salí:

Pestaña Perfil React DevTools que muestra el gráfico de llamas

¡Agradable! Notarás que esta es la misma interacción que la última vez (muestra la página después del registro) y pasamos de 13.7ms a 6.5ms. Buena mejora!

Pero uh oh, ¿qué es esta Anonymouscosa componente en todo el lugar? ¿Y tenemos un componente llamado eeotro llamado Z? ¿Eh? ¿Que está pasando aqui? Bueno, debido a que estamos creando nuestra aplicación para producción, estamos minimizando nuestro código para que sea más rápido cargarlo / analizarlo, lo cual es algo bueno para nuestros usuarios finales, pero algo malo para nuestra medición de rendimiento porque es difícil para nosotros saber cuál de estos componentes es el culpable de nuestros problemas de rendimiento.

Desactivar el cambio de nombre de la función

React sabe cómo llamar a sus componentes en función de la namepropiedad del componente:

1 función AwesomeAppComponent ( ) {
2 return < div > Impresionante < / div >
3}
4consola . log ( AwesomeAppComponent . name ) // <- registra «AwesomeAppComponent»
5
6La clase LessAwesomeAppComponent extiende React . Componente {
7 representación ( ) {
8 return < div > Menos impresionante < / div >
9 }
10}
11consola . log ( LessAwesomeAppComponent . name ) // <- registra «LessAwesomeAppComponent»
Sin embargo, cuando construimos nuestro código con un «uglifier» o un «minifier», la herramienta cambia esos nombres de una manera que hace que nuestro código funcione igual que antes, pero reduce el tamaño de archivo de nuestro archivo JavaScript de producción que mejora el rendimiento :
1 función a ( ) {
2 return < div > Impresionante < / div >
3}
4consola . log ( a . name ) // <- registra «a»
5
6la clase b se extiende Reaccionar . Componente {
7 representación ( ) {
8 return < div > Menos impresionante < / div >
9 }
10}
11consola . log ( b . name ) // <- registra «b»

Es por eso que estamos viendo estos nombres divertidos en nuestras mediciones de rendimiento. Por lo tanto, debemos deshabilitar esta función de manipulación.

La aplicación Create React utiliza una herramienta llamada Terser via terser-webpack-plugin para hacer la minificación, por lo que simplemente necesitamos actualizar la configuración para preservar la función y los nombres de clase.

Entonces, en el mismo archivo de configuración del paquete web, desplácese hacia abajo hasta donde está configurado el complemento y modifíquelo así:

1// … alguna configuración …
2nuevo TerserPlugin ( {
3 opciones disponibles : {
4 // … alguna otra configuración …
5 faltantes : {
6 safari10 : cierto ,
7 },
8 keep_classnames : verdadero ,
9 keep_fnames : verdadero ,
10 // … algo más de configuración …
11 },
12 // … aún más config …
13})
Con keep_classnameskeep_fnamesconfigurado para true, ahora intentemos construir nuestro código de aplicación y ejecutar una sesión de creación de perfiles una vez más.
Pestaña Perfil React DevTools que muestra el gráfico de llamas

¡El más excelente! ¡Ahora tenemos una sesión de perfil que nos muestra los nombres de todos nuestros componentes y se están ejecutando usando un código similar al código que nuestros usuarios finales ejecutarán mucho más de cerca!

Peligro: Perfilar con una computadora rápida

Les garantizo que la mayoría de ustedes que están leyendo esto ahora están desarrollando su aplicación con un dispositivo que es mucho más poderoso que la mayoría de las personas que usan la aplicación. No hay sustituto para probar su aplicación en los dispositivos que usarán los usuarios. Dicho esto, puede obtener una idea mucho mejor del rendimiento real de su aplicación si acelera su CPU para simular la experiencia de algunos usuarios de su aplicación.

Entonces hagamos eso. Haga clic en la pestaña «Rendimiento» de Chrome DevTools, luego en el ícono de ajustes para mostrar la configuración, luego en la opción CPU, seleccione «6x desaceleración».

Ficha de rendimiento de Chrome DevTools que muestra la ralentización de CPU 6x seleccionada

Ahora haz todo de nuevo y comprueba la diferencia:

Pestaña Perfil React DevTools que muestra el gráfico de llamas

¡Uf! 31.8ms! Eso es bastante la desaceleración! Obtenga más información sobre el impacto de ese momento en la experiencia del usuario en esta publicación de blog titulada Rendering Performance . ¡Esto puede ser algo que valga la pena considerar!

Conclusión

Solo hemos cubierto lo que necesita hacer para comenzar a perfilar correctamente una aplicación React, pero esperamos que haya aprendido lo suficiente como para probarla en su propia aplicación y comenzar a explorar las implicaciones de rendimiento de su aplicación.

¡Buena suerte!