En Chrome 102, verás un nuevo panel experimental, Estadísticas de rendimiento, en tus Herramientas para desarrolladores. En esta publicación, analizaremos no solo por qué trabajamos en un panel nuevo, sino también los desafíos técnicos que enfrentamos y las decisiones que tomamos en el camino.
¿Por qué crear otro panel?
(Si aún no lo viste, publicamos un video sobre por qué creamos el panel de Performance Insights y cómo puedes obtener estadísticas prácticas sobre el rendimiento de tu sitio web con él).
El panel de rendimiento existente es un excelente recurso si deseas ver todos los datos de tu sitio web en un solo lugar, pero sentimos que podría ser un poco abrumador. Si no eres un experto en rendimiento, es difícil saber exactamente qué buscar y qué partes de la grabación son relevantes.
Ingresa al panel Insights, en el que puedes ver una línea de tiempo de tu registro y analizar los datos, pero también obtener una lista útil de lo que DevTools considera que son las principales "estadísticas" que vale la pena investigar. Las estadísticas identificarán problemas como las solicitudes que bloquean la renderización, los cambios de diseño y las tareas largas, entre otros, que pueden afectar negativamente el rendimiento de carga de la página de tu sitio web y, específicamente, las puntuaciones de las Métricas web esenciales (CWV) de tu sitio. Además de marcar los problemas, Performance Insights te proporcionará sugerencias prácticas para mejorar tus puntuaciones de las CVW y vínculos a más recursos y documentación.
Este panel es experimental y queremos conocer tu opinión. Comunícate con nosotros si encuentras errores o tienes solicitudes de funciones que crees que te ayudarán a mejorar el rendimiento de tu sitio.
Cómo creamos las Estadísticas de rendimiento
Al igual que el resto de DevTools, creamos Performance Insights en TypeScript y usamos componentes web, respaldados por lit-html, para crear la interfaz de usuario. La diferencia de Performance Insights radica en que la interfaz de IU principal es un elemento canvas
de HTML, y la línea de tiempo se dibuja en este lienzo. Gran parte de la complejidad proviene de la administración de este lienzo: no solo dibujar los detalles correctos en el lugar correcto, sino también administrar los eventos del mouse (por ejemplo, ¿dónde hizo clic el usuario en el lienzo?). ¿Hicieron clic en un evento que dibujamos?) y garantizar que volvamos a renderizar el lienzo de manera eficaz.
Varias pistas en un solo lienzo
Para un sitio web determinado, hay varios "registros" que queremos renderizar, y cada uno representa una categoría diferente de datos. Por ejemplo, el panel de estadísticas mostrará tres segmentos de forma predeterminada:
A medida que sigamos agregando funciones al panel, esperamos que se agreguen más pistas.
Nuestra idea inicial era que cada uno de estos segmentos renderizara su propio <canvas>
, de modo que la vista principal se convirtiera en varios elementos de lienzo apilados verticalmente. Esto simplificaría la renderización a nivel de la pista, ya que cada pista podría renderizarse de forma aislada y no habría peligro de que una pista se renderizara fuera de sus límites, pero, lamentablemente, este enfoque tiene dos problemas principales:
Los elementos canvas
son costosos de renderizar (o volver a renderizar); tener varios lienzos es más costoso que tener un solo lienzo, incluso si ese lienzo es más grande.
Renderizar cualquier superposición que abarque varias pistas (por ejemplo, líneas verticales para marcar eventos como el tiempo del FCP) se vuelve complejo: tenemos que renderizar en varios lienzos y asegurarnos de que todos se rendericen juntos y se alineen correctamente.
Usar un solo canvas
para toda la IU significaba que debíamos encontrar la manera de garantizar que cada pista se renderizara en las coordenadas correctas y no se desbordara en otra pista. Por ejemplo, si un segmento en particular tiene 100 px de alto, no podemos permitir que renderice algo que tenga 120 px de alto y que se extienda al segmento que está debajo. Para resolver este problema, podemos usar clip
. Antes de renderizar cada pista, dibujamos un rectángulo que representa la ventana de pista visible. Esto garantiza que el lienzo recorte cualquier ruta dibujada fuera de estos límites.
canvasContext.beginPath();
canvasContext.rect(
trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();
Tampoco queríamos que cada pista tuviera que conocer su posición vertical: cada pista debería renderizarse como si se renderizara en (0, 0), y tenemos un componente de nivel superior (que llamamos TrackManager
) para administrar la posición general de la pista. Esto se puede hacer con translate
, que traslada el lienzo según una posición (x, y) determinada. Por ejemplo:
canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide
A pesar de que el código rect
establece 0, 0
como la posición, la traducción general aplicada hará que el rectángulo se renderice en 0, 10
. Esto nos permite trabajar en función de las pistas como si renderizáramos en (0, 0) y hacer que nuestro administrador de pistas traduzca a medida que renderiza cada pista para garantizar que cada una se renderice correctamente debajo de la anterior.
Lienzos fuera de la pantalla para pistas y momentos destacados
La renderización de Canvas es relativamente costosa, y queremos asegurarnos de que el panel de estadísticas permanezca fluido y responsivo mientras trabajas con él. A veces, no puedes evitar tener que volver a renderizar todo el lienzo, por ejemplo, si cambias el nivel de zoom, debemos comenzar de nuevo y volver a renderizar todo. El nuevo renderizado del lienzo es particularmente costoso porque no se puede volver a renderizar solo una pequeña parte; es necesario borrar todo el lienzo y volver a dibujarlo. Esto es diferente de la nueva renderización del DOM, en la que las herramientas pueden calcular el trabajo mínimo requerido y no quitar todo y comenzar de nuevo.
Un área en la que tuvimos problemas visuales fue el resaltado. Cuando colocas el cursor sobre las métricas en el panel, las destacamos en el cronograma. Del mismo modo, si colocas el cursor sobre una estadística para un evento determinado, dibujamos un borde azul alrededor de ese evento.
Esta función se implementó por primera vez detectando el movimiento del mouse sobre un elemento que activa un resaltado y, luego, dibujando ese resaltado directamente en el lienzo principal. El problema surge cuando tenemos que quitar el resaltado, ya que la única opción es volver a dibujar todo. Es imposible volver a dibujar solo el área donde estaba el resaltado (no sin grandes cambios en la arquitectura), pero volver a dibujar todo el lienzo solo porque queremos quitar un borde azul alrededor de un elemento se sintió como una exageración. También se retrasaba visualmente si movías rápidamente el mouse sobre diferentes elementos para activar varios destacados en rápida sucesión.
Para solucionar este problema, dividimos nuestra IU en dos lienzos fuera de la pantalla: el lienzo “principal”, en el que se renderizan las pistas, y el lienzo “destacados”, en el que se dibujan los destacados. Luego, copiamos esos lienzos en el único lienzo que el usuario ve en la pantalla. Podemos usar el método drawImage
en un contexto de lienzo, que puede tomar otro lienzo como su fuente.
Hacer esto significa que quitar un elemento destacado no hace que se vuelva a dibujar el lienzo principal: en cambio, podemos borrar el lienzo en pantalla y, luego, copiar el lienzo principal en el lienzo visible. Copiar un lienzo es económico, pero dibujar es costoso. Por lo tanto, al mover los destacados a un lienzo separado, evitamos ese costo cuando activamos y desactivamos los destacados.
Análisis de registros probado de forma integral
Uno de los beneficios de crear una función nueva desde cero es que puedes reflexionar sobre las decisiones técnicas que tomaste anteriormente y realizar mejoras. Una de las cosas que queríamos mejorar era dividir explícitamente nuestro código en dos partes casi completamente distintas:
Analiza el archivo de registro y extrae los datos necesarios. Renderiza un conjunto de pistas.
Mantener el análisis (parte 1) separado del trabajo de la IU (parte 2) nos permitió crear un sistema de análisis sólido. Cada registro se ejecuta a través de una serie de controladores que se encargan de diferentes aspectos: un LayoutShiftHandler
calcula toda la información que necesitamos para los cambios de diseño y un NetworkRequestsHandler
se encarga exclusivamente de extraer las solicitudes de red. Tener este paso de análisis explícito en el que tenemos diferentes controladores responsables de diferentes partes del registro también ha sido beneficioso: el análisis del registro puede ser muy complicado, y ayuda poder enfocarse en un problema a la vez.
También pudimos probar de forma integral nuestro análisis de registros tomando grabaciones en Herramientas para desarrolladores, guardándolas y, luego, cargándolas como parte de nuestro paquete de pruebas. Esto es excelente porque podemos realizar pruebas con registros reales y no generar grandes cantidades de datos de registros falsos que podrían volverse obsoletos.
Pruebas de capturas de pantalla para la IU de Canvas
En relación con las pruebas, solemos probar nuestros componentes de frontend renderizándolos en el navegador y asegurándonos de que se comporten según lo previsto. Podemos enviar eventos de clic para activar actualizaciones y afirmar que el DOM que generan los componentes es correcto. Este enfoque nos funciona bien, pero no es adecuado cuando se trata de renderizar en un lienzo, ya que no hay forma de inspeccionar un lienzo y determinar qué se dibuja allí. Por lo tanto, nuestro enfoque habitual de renderizar y, luego, consultar no es adecuado.
Para habilitar cierta cobertura de pruebas, recurrimos a las pruebas de capturas de pantalla. Cada prueba inicia un lienzo, renderiza el segmento que queremos probar y, luego, toma una captura de pantalla del elemento del lienzo. Luego, esta captura de pantalla se almacena en nuestra base de código, y las ejecuciones de pruebas futuras compararán la captura de pantalla almacenada con la que generen. Si las capturas de pantalla son diferentes, la prueba fallará. También proporcionamos una marca para ejecutar la prueba y forzar una actualización de la captura de pantalla cuando cambiamos intencionalmente la renderización y necesitamos que se actualice la prueba.
Las pruebas de capturas de pantalla no son perfectas y son un poco directas. Solo puedes probar que todo el componente se renderice según lo esperado, en lugar de realizar aserciones más específicas. Inicialmente, las usábamos en exceso para asegurarnos de que cada componente (HTML o lienzo) se renderizara correctamente. Esto ralentizó drásticamente nuestro conjunto de pruebas y generó problemas en los que pequeños ajustes de la IU casi irrelevantes (como cambios sutiles de color o la adición de un margen entre elementos) provocaron que fallaran varias capturas de pantalla y que fuera necesario actualizarlas. Ahora redujimos el uso de capturas de pantalla y las usamos solo para los componentes basados en el lienzo. Este equilibrio nos ha funcionado bien hasta ahora.
Conclusión
Crear el nuevo panel de Estadísticas de rendimiento fue una experiencia muy agradable y educativa para el equipo. Aprendimos mucho sobre los archivos de registro, cómo trabajar con el lienzo y mucho más. Esperamos que disfrutes usar el nuevo panel y estamos ansiosos por conocer tus comentarios.
Para obtener más información sobre el panel de estadísticas de rendimiento, consulta Estadísticas de rendimiento: Obtén estadísticas prácticas sobre el rendimiento de tu sitio web.
Descarga los canales de vista previa
Considera usar Chrome Canary, Dev o Beta como tu navegador de desarrollo predeterminado. Estos canales de versión preliminar te brindan acceso a las funciones más recientes de DevTools, te permiten probar las APIs de vanguardia de la plataforma web y te ayudan a encontrar problemas en tu sitio antes de que lo hagan tus usuarios.
Comunícate con el equipo de Herramientas para desarrolladores de Chrome
Usa las siguientes opciones para analizar las nuevas funciones, las actualizaciones o cualquier otro tema relacionado con las Herramientas para desarrolladores.
- Envíanos tus comentarios y solicitudes de funciones a crbug.com.
- Informa un problema de DevTools con Más opciones > Ayuda > Informar un problema de DevTools en DevTools.
- Envía un tuit a @ChromeDevTools.
- Deja comentarios en los videos de Novedades de las Herramientas para desarrolladores de YouTube o en los videos de Sugerencias sobre las Herramientas para desarrolladores de YouTube.