Identifica el código JavaScript de ejecución pesada

La ejecución de JavaScript pesado puede tener un efecto perjudicial tanto en el rendimiento de la carga de página como en la interactividad. Las aplicaciones web modernas dependen más que nunca de JavaScript, que proviene de múltiples fuentes. Esto incluye el código de la aplicación en sí (y el código del framework en el que se basa), así como las secuencias de comandos de terceros que agregan funciones, como widgets de chat y reproductores de video. Las secuencias de comandos de marketing y estadísticas en segundo plano también son contribuyentes comunes que son muy fáciles de olvidar.

Identificar las causas raíz de una página web que no responde puede ser difícil, ya que se requiere cierta experiencia para ejecutar el seguimiento o la generación de perfiles del rendimiento web y saber cómo interpretar los resultados. Además, los datos de campo suelen ser muy diferentes de los datos de laboratorio, que solo replican un pequeño subconjunto de situaciones de usuarios reales. Esto puede dificultar la identificación de las causas raíz del rendimiento deficiente, en especial para las interacciones.

La API de Long Animation Frames es una API ligera que se puede usar para identificar el código de JavaScript que se ejecuta con mucha carga en el campo. Una secuencia de comandos de ejecución pesada puede ser una sola secuencia de comandos de larga duración o una secuencia de comandos que se ejecuta varias veces durante el ciclo de vida de la página.

Cómo implementarlo

Los fotogramas de animación largos se supervisan con la interfaz PerformanceObserver. Emite una entrada long-animation-frame cuando un fotograma de animación tarda más de 50 ms en renderizarse. La entrada contiene información sobre el fotograma de animación largo, incluida su duración y las secuencias de comandos que se ejecutaron durante el fotograma.

La entrada long-animation-frame contiene una propiedad scripts, que es un array de objetos PerformanceScript. Cada objeto PerformanceScript contiene información sobre la secuencia de comandos que se ejecutó durante el fotograma de animación largo, incluidos el sourceURL y el duration de la secuencia de comandos.

Ejemplo de identificación de las secuencias de comandos de mayor duración que contribuyen a los fotogramas de animación largos

// Accumulate all script entries across the page lifecycle so no
// data is lost between observer callbacks.
const allScripts = [];

const observer = new PerformanceObserver(list => {
  // Collect all script entries across frames to find the biggest offenders.
  allScripts.push(...list.getEntries().flatMap(entry => entry.scripts));

  // Group by sourceURL so you can identify which scripts contribute
  // the most total time, even if each individual invocation is short.
  const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
  const scriptsBySource = scriptSource.map(sourceURL => ([sourceURL,
      allScripts.filter(script => script.sourceURL === sourceURL)
  ]));
  const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
    sourceURL,
    count: scripts.length,
    totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
  }));

  // Only include scripts above a certain threshold to reduce noise.
  const heavyScripts = processedScripts.filter(script => {
    return script.totalDuration > 100;
  });

  // Sort by total duration so the worst offenders appear first,
  // making it easier to prioritize optimization efforts.
  heavyScripts.sort((a, b) => b.totalDuration - a.totalDuration);

  // Log to the console for local debugging. In production, replace
  // this with a call to send the data to your analytics service.
  console.table(heavyScripts);
});

// Use buffered: true to capture any long frames that occurred before
// this observer was registered.
observer.observe({type: 'long-animation-frame', buffered: true});

Prácticas recomendadas

  • SÍ prefiere la API de Long Animation Frames en lugar de alternativas como la API de JS Self-Profiling, que genera una mayor sobrecarga de tiempo de ejecución.
  • SÍ resume la información clave, ya que la API de Long Animation Frames contiene muchos detalles.
  • SÍ envía la información requerida a un servicio de estadísticas en producción.

Compatibilidad con navegadores y estrategias de resguardo

Los navegadores que no admiten la API de Long Animation Frames la ignoran, por lo que se puede usar de forma segura sin resguardos. En la mayoría de los casos, las oportunidades de rendimiento que identifica también se aplicarán a otros navegadores.