Identificar JavaScripts pesados

O JavaScript pesado pode ter um efeito prejudicial na performance de carregamento de página e na interatividade. Os aplicativos da Web modernos dependem mais do que nunca do JavaScript, de várias fontes. Isso inclui o próprio código do aplicativo (e o código do framework em que ele se baseia), além de scripts de terceiros que adicionam funcionalidades, como widgets de chat e players de vídeo. Scripts de análise e marketing em segundo plano também são fatores comuns que costumam ser esquecidos.

Identificar as causas raiz de uma página da Web que não responde pode ser difícil, exigindo certa experiência para executar o rastreamento ou a criação de perfil de desempenho da Web e interpretar os resultados. Além disso, os dados de campo costumam ser muito diferentes dos dados de laboratório, que replicam apenas um pequeno subconjunto de cenários de usuários reais. Isso pode dificultar a identificação das causas raiz do desempenho ruim, especialmente para interações.

A API Long Animation Frames é uma API leve que pode ser usada para identificar JavaScript pesado em campo. Um script de execução pesada pode ser um único script de longa duração ou um script que é executado várias vezes durante o ciclo de vida da página.

Como fazer a implementação

Os frames longos de animação são monitorados usando a interface PerformanceObserver. Ele emite uma entrada long-animation-frame quando um frame de animação leva mais de 50 ms para ser renderizado. A entrada contém informações sobre o frame longo de animação, incluindo a duração do frame e os scripts que foram executados durante ele.

A entrada long-animation-frame contém uma propriedade scripts, que é uma matriz de objetos PerformanceScript. Cada objeto PerformanceScript contém informações sobre o script que foi executado durante o frame longo de animação, incluindo o sourceURL e o duration do script.

Exemplo de identificação dos scripts de execução mais longa que contribuem para frames longos de animação

// 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áticas recomendadas

  • DÊ preferência à API Long Animation Frames em vez de alternativas como a API JS Self-Profiling, que tem uma sobrecarga de execução maior.
  • FAÇA um resumo das informações principais, já que a API Long Animation Frames contém muitos detalhes.
  • RECOMENDADO: envie as informações necessárias para um serviço de análise em produção.

Suporte ao navegador e estratégias de substituição

A API Long Animation Frames é ignorada por navegadores que não são compatíveis com ela. Portanto, pode ser usada com segurança sem substitutos. Na maioria dos casos, as oportunidades de performance identificadas também se aplicam a outros navegadores.