Измерение критического пути рендеринга

Илья Григорик
Ilya Grigorik

Опубликовано: 31 марта 2014 г.

Основа любой эффективной стратегии повышения производительности — это качественные измерения и инструменты. Нельзя оптимизировать то, что невозможно измерить. В этом руководстве рассматриваются различные подходы к измерению производительности критического пути рендеринга (КРП).

  • Подход Lighthouse запускает серию автоматизированных тестов страницы, а затем генерирует отчёт о её CRP-эффективности. Этот подход обеспечивает быстрый и базовый обзор CRP-эффективности конкретной страницы, загруженной в браузер, что позволяет быстро тестировать, итерировать и улучшать её производительность.
  • Подход Navigation Timing API собирает метрики Real User Monitoring (RUM) . Как следует из названия, эти метрики собираются на основе реальных взаимодействий пользователей с вашим сайтом и дают точное представление о реальной эффективности CRP, которую ощущают ваши пользователи на различных устройствах и в различных сетевых условиях.

В целом, хорошим подходом будет использование Lighthouse для выявления очевидных возможностей оптимизации CRP, а затем оснащение вашего кода API Navigation Timing для отслеживания того, как ваше приложение работает в реальных условиях.

Аудит страницы с помощью Lighthouse

Lighthouse — это инструмент аудита веб-приложений, который проводит серию тестов на заданной странице и затем отображает результаты в консолидированном отчёте. Вы можете запустить Lighthouse как расширение Chrome или модуль NPM, что полезно для интеграции Lighthouse с системами непрерывной интеграции.

Чтобы начать, прочтите статью «Аудит веб-приложений с помощью Lighthouse» .

При запуске Lighthouse как расширения Chrome результаты CRP вашей страницы должны быть аналогичными и содержать длительность цепочек и порядок файлов, загруженных браузером.

Сочетание API навигации и других событий браузера, генерируемых при загрузке страницы, позволяет фиксировать и записывать реальную производительность CRP любой страницы.

Каждая метка на диаграмме соответствует метке времени высокого разрешения, которую браузер отслеживает для каждой загружаемой страницы. Эта диаграмма игнорирует все метки времени, связанные с сетью.

Так что же означают эти временные метки?

  • domLoading : это начальная метка времени всего процесса, браузер собирается начать анализ первых полученных байтов HTML-документа.
  • domInteractive : отмечает момент, когда браузер завершил разбор всего HTML и построение DOM завершено.
  • domContentLoaded : отмечает момент, когда DOM готов и нет таблиц стилей, блокирующих выполнение JavaScript, — это означает, что теперь мы можем (потенциально) построить дерево рендеринга.
    • Многие JavaScript-фреймворки ждут этого события, прежде чем начать выполнение собственной логики. Поэтому браузер фиксирует временные метки EventStart и EventEnd , позволяя нам отслеживать длительность выполнения.
  • domComplete : как следует из названия, вся обработка завершена и все ресурсы на странице (изображения и т. д.) завершили загрузку — другими словами, индикатор загрузки перестал вращаться.
  • loadEvent : на последнем этапе загрузки каждой страницы браузер запускает событие onload , которое может запустить дополнительную логику приложения.

Спецификация HTML определяет конкретные условия для каждого события: когда оно должно быть вызвано, какие условия должны быть соблюдены и другие важные моменты.

Для наших целей мы сосредоточимся на нескольких ключевых этапах развития CRP:

  • domInteractive отмечает готовность DOM.
  • domContentLoaded обычно отмечает готовность как DOM, так и CSSOM .
    • Если парсер не блокирует JavaScript, то DOMContentLoaded срабатывает сразу после domInteractive .
  • domComplete отмечает готовность страницы и всех ее подресурсов.
<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <script>
      function measureCRP() {
        var t = window.performance.timing,
          interactive = t.domInteractive - t.domLoading,
          dcl = t.domContentLoadedEventStart - t.domLoading,
          complete = t.domComplete - t.domLoading;
        var stats = document.createElement('p');
        stats.textContent =
          'interactive: ' +
          interactive +
          'ms, ' +
          'dcl: ' +
          dcl +
          'ms, complete: ' +
          complete +
          'ms';
        document.body.appendChild(stats);
      }
    </script>
  </head>
  <body onload="measureCRP()">
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

Попробуй это

В этом примере API Navigation Timing собирает все соответствующие временные метки. Наш код ожидает срабатывания события onload , которое происходит после domInteractive , domContentLoaded и domComplete . Затем он вычисляет разницу между различными временными метками.

Теперь у нас есть несколько конкретных контрольных точек для отслеживания и базовая функция для вывода этих показателей. Вы можете изменить этот код так, чтобы отправлять эти показатели на аналитический сервер вместо вывода результатов. Это позволит вам отслеживать эффективность страниц и определять, какие из них могут выиграть от оптимизации.

А как насчет DevTools?

Хотя в этих документах иногда используется панель Chrome DevTools Network для иллюстрации концепций CRP, DevTools не очень подходит для измерения CRP, поскольку не имеет встроенного механизма изоляции критически важных ресурсов. Для выявления таких ресурсов можно провести аудит Lighthouse .