Пользовательские метрики

Очень важно иметь ориентированные на пользователя показатели , которые можно измерить повсеместно на любом веб-сайте. Эти показатели позволяют:

  • Поймите, как реальные пользователи воспринимают Интернет в целом.
  • Сравните свой сайт с сайтом конкурента.
  • Отслеживайте полезные и полезные данные в своих аналитических инструментах без необходимости писать собственный код.

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

Специальные метрики позволяют измерять аспекты взаимодействия с вашим сайтом, которые могут относиться только к нему, например:

  • Сколько времени требуется одностраничному приложению (SPA) для перехода с одной «страницы» на другую.
  • Сколько времени требуется странице для отображения данных, полученных из базы данных для вошедших в систему пользователей.
  • Сколько времени требуется приложению, отображаемому на стороне сервера (SSR), для гидратации .
  • Коэффициент попадания в кеш ресурсов, загруженных вернувшимися посетителями.
  • Задержка событий щелчка или клавиатуры в игре.

API для измерения пользовательских метрик

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

Например, можно определить, заблокирован ли основной поток из-за длительного выполнения задач JavaScript, запустив цикл requestAnimationFrame и вычислив разницу между каждым кадром. Если разница значительно превышает частоту кадров дисплея, вы можете сообщить об этом как о длительной задаче. Однако такие хаки не рекомендуются, поскольку они сами по себе влияют на производительность (например, разряжая батарею).

Первое правило эффективного измерения производительности — убедиться, что ваши методы измерения производительности сами по себе не вызывают проблем с производительностью. Поэтому для любых специальных показателей, которые вы измеряете на своем сайте, лучше всего использовать один из следующих API, если это возможно.

API наблюдателя за производительностью

Поддержка браузера

  • Хром: 52.
  • Край: 79.
  • Фаерфокс: 57.
  • Сафари: 11.

Источник

API Performance Observer — это механизм, который собирает и отображает данные из всех других API производительности, обсуждаемых на этой странице. Понимание этого имеет решающее значение для получения качественных данных.

Вы можете использовать PerformanceObserver для пассивной подписки на события, связанные с производительностью. Это позволяет обратным вызовам API запускаться в периоды простоя , что означает, что они обычно не влияют на производительность страницы.

Чтобы создать PerformanceObserver , передайте ему обратный вызов, который будет запускаться при отправке новых записей о производительности. Затем вы сообщаете наблюдателю, какие типы записей следует прослушивать, используя метод observe() :

const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// Log the entry and all associated details.
    console
.log(entry.toJSON());
 
}
});

po
.observe({type: 'some-entry-type'});

В следующих разделах перечислены все различные типы записей, доступные для наблюдения, но в новых браузерах вы можете проверить, какие типы записей доступны, с помощью статического свойства PerformanceObserver.supportedEntryTypes .

Обратите внимание на записи, которые уже произошли

По умолчанию объекты PerformanceObserver могут наблюдать записи только по мере их появления. Это может вызвать проблемы, если вы хотите отложенно загружать код аналитики производительности, чтобы он не блокировал ресурсы с более высоким приоритетом.

Чтобы получить исторические записи (после того, как они произошли), установите для флага buffered значение true при вызове observe() . Браузер будет включать исторические записи из своего буфера записей производительности при первом вызове обратного вызова PerformanceObserver , вплоть до максимального размера буфера для этого типа .

po.observe({
  type
: 'some-entry-type',
  buffered
: true,
});

Устаревшие API производительности, которых следует избегать

До API Performance Observer разработчики могли получать доступ к записям производительности, используя следующие три метода, определенные в объекте performance :

Хотя эти API по-прежнему поддерживаются, их использование не рекомендуется, поскольку они не позволяют отслеживать появление новых записей. Кроме того, многие новые API (например, largest-contentful-paint ) не предоставляются через объект performance , они предоставляются только через PerformanceObserver .

Если вам не нужна совместимость с Internet Explorer, лучше избегать этих методов в своем коде и в дальнейшем использовать PerformanceObserver .

API синхронизации пользователя

Поддержка браузера

  • Хром: 28.
  • Край: 12.
  • Фаерфокс: 38.
  • Сафари: 11.

Источник

API пользовательского времени — это API общего назначения для измерения метрик, основанных на времени. Он позволяет произвольно отмечать моменты времени, а затем позже измерять продолжительность между этими отметками.

// Record the time immediately before running a task.
performance
.mark('myTask:start');
await doMyTask
();

// Record the time immediately after running a task.
performance
.mark('myTask:end');

// Measure the delta between the start and end of the task
performance
.measure('myTask', 'myTask:start', 'myTask:end');

Хотя такие API, как Date.now() или performance.now() предоставляют аналогичные возможности, преимущество использования User Timing API заключается в том, что он хорошо интегрируется с инструментами повышения производительности. Например, Chrome DevTools визуализирует измерения пользовательского времени на панели «Производительность» , а многие поставщики аналитики также автоматически отслеживают любые ваши измерения и отправляют данные о продолжительности на свой аналитический сервер.

Чтобы сообщить об измерениях пользовательского времени, вы можете использовать PerformanceObserver и зарегистрироваться для наблюдения за записями типа measure :

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// Log the entry and all associated details.
    console
.log(entry.toJSON());
 
}
});

// Start listening for `measure` entries to be dispatched.
po
.observe({type: 'measure', buffered: true});

API длинных задач

Поддержка браузера

  • Хром: 58.
  • Край: 79.
  • Firefox: не поддерживается.
  • Сафари: не поддерживается.

Источник

API длинных задач полезен для определения того, когда основной поток браузера блокируется на достаточно долгое время, чтобы повлиять на частоту кадров или задержку ввода. API будет сообщать обо всех задачах, которые выполняются дольше 50 миллисекунд.

Каждый раз, когда вам нужно запустить дорогостоящий код или загрузить и выполнить большие сценарии, полезно отслеживать, не блокирует ли этот код основной поток. Фактически, многие метрики более высокого уровня создаются поверх самого API длинных задач (например, время взаимодействия (TTI) и общее время блокировки (TBT) ).

Чтобы определить, когда выполняются длительные задачи, вы можете использовать PerformanceObserver и зарегистрироваться для наблюдения за записями типа longtask :

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// Log the entry and all associated details.
    console
.log(entry.toJSON());
 
}
});

// Start listening for `longtask` entries to be dispatched.
po
.observe({type: 'longtask', buffered: true});

API длинных кадров анимации

Поддержка браузера

  • Хром: 123.
  • Край: 123.
  • Firefox: не поддерживается.
  • Сафари: не поддерживается.

Источник

API длинных кадров анимации — это новая версия API длинных задач, которая рассматривает длинные кадры , а не длинные задачи , длительностью более 50 миллисекунд. Это устраняет некоторые недостатки API длинных задач , в том числе лучшую атрибуцию и более широкий спектр потенциально проблемных задержек.

Чтобы определить, когда происходят длинные кадры, вы можете использовать PerformanceObserver и зарегистрироваться для наблюдения за записями типа long-animation-frame :

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// Log the entry and all associated details.
    console
.log(entry.toJSON());
 
}
});

// Start listening for `long-animation-frame` entries to be dispatched.
po
.observe({type: 'long-animation-frame', buffered: true});

API синхронизации элементов

Поддержка браузера

  • Хром: 77.
  • Край: 79.
  • Firefox: не поддерживается.
  • Сафари: не поддерживается.

Источник

Метрика «Наибольшая отрисовка содержимого» (LCP) полезна для определения того, когда на экране было нарисовано самое большое изображение или текстовый блок, но в некоторых случаях необходимо измерить время рендеринга другого элемента.

В этих случаях используйте Element Timing API . API LCP фактически построен на основе API синхронизации элементов и добавляет автоматические отчеты о самом большом элементе с содержимым, но вы также можете создавать отчеты о других элементах, явно добавляя к ним атрибут elementtiming и регистрируя PerformanceObserver для наблюдения за типом записи element .

<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
<!-- ... -->

<script>
 
const po = new PerformanceObserver((entryList) => {
   
for (const entry of entryList.getEntries()) {
     
// Log the entry and all associated details.
      console
.log(entry.toJSON());
   
}
 
});

 
// Start listening for `element` entries to be dispatched.
  po
.observe({type: 'element', buffered: true});
</script>

API синхронизации событий

Поддержка браузера

  • Хром: 76.
  • Край: 79.
  • Фаерфокс: 89.
  • Сафари: не поддерживается.

Источник

Метрика «Взаимодействие с следующей отрисовкой» (INP) оценивает общую скорость реагирования страницы, наблюдая за всеми взаимодействиями с щелчками, касаниями и клавиатурой на протяжении всего существования страницы. INP страницы чаще всего представляет собой взаимодействие, выполнение которого заняло больше всего времени: с момента, когда пользователь инициировал взаимодействие, до момента, когда браузер рисует следующий кадр, показывающий визуальный результат ввода пользователя.

Метрика INP стала возможной благодаря API синхронизации событий . Этот API предоставляет ряд временных меток, которые возникают в течение жизненного цикла события, в том числе:

  • startTime : время, когда браузер получает событие.
  • processingStart : время, когда браузер может начать обработку обработчиков события.
  • processingEnd : время, когда браузер завершает выполнение всего синхронного кода, инициированного обработчиками событий для этого события.
  • duration : время (округленное до 8 миллисекунд по соображениям безопасности) между получением браузером события и возможностью отрисовки следующего кадра после завершения выполнения всего синхронного кода, инициированного обработчиками событий.

В следующем примере показано, как использовать эти значения для создания пользовательских измерений:

const po = new PerformanceObserver((entryList) => {
 
// Get the last interaction observed:
 
const entries = Array.from(entryList.getEntries()).forEach((entry) => {
   
// Get various bits of interaction data:
   
const inputDelay = entry.processingStart - entry.startTime;
   
const processingTime = entry.processingEnd - entry.processingStart;
   
const presentationDelay = entry.startTime + entry.duration - entry.processingEnd;
   
const duration = entry.duration;
   
const eventType = entry.name;
   
const target = entry.target || "(not set)"

    console
.log("----- INTERACTION -----");
    console
.log(`Input delay (ms): ${inputDelay}`);
    console
.log(`Event handler processing time (ms): ${processingTime}`);
    console
.log(`Presentation delay (ms): ${presentationDelay}`);
    console
.log(`Total event duration (ms): ${duration}`);
    console
.log(`Event type: ${eventType}`);
    console
.log(target);
 
});
});

// A durationThreshold of 16ms is necessary to include more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po
.observe({type: 'event', buffered: true, durationThreshold: 16});

API синхронизации ресурсов

Поддержка браузера

  • Хром: 29.
  • Край: 12.
  • Фаерфокс: 35.
  • Сафари: 11.

Источник

API синхронизации ресурсов дает разработчикам подробную информацию о том, как были загружены ресурсы для конкретной страницы. Несмотря на название API, предоставляемая им информация не ограничивается только данными о времени (хотя их достаточно ). Другие данные, к которым вы можете получить доступ, включают:

  • initiatorType : как был получен ресурс: например, из тега <script> или <link> или из вызова fetch() .
  • nextHopProtocol : протокол, используемый для получения ресурса, например h2 или quic .
  • encodedBodySize / decodedBodySize ]: размер ресурса в закодированном или декодированном виде (соответственно)
  • transferSize : размер ресурса, который был фактически передан по сети. Когда ресурсы заполняются кешем, это значение может быть намного меньше, чем encodedBodySize , а в некоторых случаях оно может быть нулевым (если повторная проверка кеша не требуется).

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

В следующем примере регистрируются все ресурсы, запрошенные страницей, и указывается, был ли каждый ресурс обработан кэшем.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// If transferSize is 0, the resource was fulfilled using the cache.
    console
.log(entry.name, entry.transferSize === 0);
 
}
});

// Start listening for `resource` entries to be dispatched.
po
.observe({type: 'resource', buffered: true});

Поддержка браузера

  • Хром: 57.
  • Край: 12.
  • Фаерфокс: 58.
  • Сафари: 15.

Источник

API синхронизации навигации аналогичен API синхронизации ресурсов, но он сообщает только о запросах навигации . Тип записи navigation также аналогичен типу записи resource , но он содержит некоторую дополнительную информацию , специфичную только для запросов навигации (например, при возникновении событий DOMContentLoaded и load ).

Одна метрика, которую многие разработчики отслеживают, чтобы понять время ответа сервера ( время до первого байта (TTFB) ), доступна с помощью API синхронизации навигации — в частности, это метка времени responseStart записи.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// If transferSize is 0, the resource was fulfilled using the cache.
    console
.log('Time to first byte', entry.responseStart);
 
}
});

// Start listening for `navigation` entries to be dispatched.
po
.observe({type: 'navigation', buffered: true});

Еще одна метрика, которая может волновать разработчиков, использующих Service Worker, — это время запуска Service Worker для запросов навигации. Это количество времени, которое требуется браузеру для запуска рабочего потока службы, прежде чем он сможет начать перехватывать события выборки.

Время запуска сервис-воркера для конкретного запроса навигации можно определить по разнице между entry.responseStart и entry.workerStart .

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
    console
.log('Service Worker startup time:',
        entry
.responseStart - entry.workerStart);
 
}
});

// Start listening for `navigation` entries to be dispatched.
po
.observe({type: 'navigation', buffered: true});

API синхронизации сервера

Поддержка браузера

  • Хром: 65.
  • Край: 79.
  • Фаерфокс: 61.
  • Сафари: 16.4.

Источник

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

Для разработчиков, которые используют сторонних поставщиков аналитики, API синхронизации сервера — единственный способ сопоставить данные о производительности сервера с другими бизнес-показателями, которые могут измеряться этими инструментами аналитики.

Чтобы указать данные синхронизации сервера в ваших ответах, вы можете использовать заголовок ответа Server-Timing . Вот пример.

HTTP/1.1 200 OK

Server-Timing: miss, db;dur=53, app;dur=47.2

Затем со своих страниц вы можете прочитать эти данные как о resource , так и о записях navigation из API-интерфейсов синхронизации ресурсов и времени навигации.

// Create the performance observer.
const po = new PerformanceObserver((list) => {
 
for (const entry of list.getEntries()) {
   
// Logs all server timing data for this response
    console
.log('Server Timing', entry.serverTiming);
 
}
});

// Start listening for `navigation` entries to be dispatched.
po
.observe({type: 'navigation', buffered: true});