Отладка производительности в полевых условиях

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

Google предоставляет две категории инструментов для измерения и отладки производительности:

  • Лабораторные инструменты: такие инструменты, как Lighthouse, где ваша страница загружается в смоделированную среду, которая может имитировать различные условия (например, медленную сеть и низкопроизводительное мобильное устройство).
  • Полевые инструменты: такие инструменты, как отчет об опыте пользователей Chrome (CrUX), который основан на совокупных данных реальных пользователей Chrome. (Обратите внимание, что данные полей, предоставляемые такими инструментами, как PageSpeed ​​Insights и Search Console , получены из данных CrUX.)

Хотя полевые инструменты предоставляют более точные данные — данные, которые на самом деле отражают то, что испытывают реальные пользователи, — лабораторные инструменты часто лучше помогают выявлять и устранять проблемы.

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

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

В связи с этим возникает важный вопрос: как можно получить отладочную информацию для Core Web Vitals или других показателей производительности от реальных пользователей на местах?

В этом посте подробно объясняется, какие API-интерфейсы вы можете использовать для сбора дополнительной отладочной информации для каждой из текущих метрик Core Web Vitals, а также даются идеи о том, как собирать эти данные в существующем инструменте аналитики.

API для атрибуции и отладки

Совокупное изменение макета (CLS)

Из всех показателей Core Web Vitals CLS , пожалуй, является тем, для которого сбор отладочной информации на местах является наиболее важным. CLS измеряется на протяжении всего жизненного цикла страницы, поэтому то, как пользователь взаимодействует со страницей (как далеко он прокручивает, на что нажимает и т. д.), может оказать существенное влияние на то, происходят ли изменения макета и какие элементы смещаются. .

Рассмотрим следующий отчет PageSpeed ​​Insights:

Отчет PageSpeed ​​Insights с различными значениями CLS
PageSpeed ​​Insights показывает как полевые, так и лабораторные данные, если они доступны, и они могут отличаться.

Значения CLS, полученные из лаборатории (Lighthouse), по сравнению с CLS, полученными в полевых условиях (данные CrUX), совершенно разные, и это имеет смысл, если учесть, что на странице может быть много интерактивного контента, который не используется при тестировании. в Маяке.

Но даже если вы понимаете, что взаимодействие с пользователем влияет на данные полей, вам все равно необходимо знать, какие элементы на странице смещаются, чтобы получить оценку 0,28 в 75-м процентиле. Интерфейс LayoutShiftAttribution делает это возможным.

Получить атрибуцию изменения макета

Интерфейс LayoutShiftAttribution отображается в каждой записи layout-shift , которую создает API Layout Instability .

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

Вот пример кода, который регистрирует каждое изменение макета, а также элементы, которые сместились:

new PerformanceObserver((list) => {
  for (const {value, startTime, sources} of list.getEntries()) {
    // Log the shift amount and other entry info.
    console.log('Layout shift:', {value, startTime});
    if (sources) {
      for (const {node, curRect, prevRect} of sources) {
        // Log the elements that shifted.
        console.log('  Shift source:', node, {curRect, prevRect});
      }
    }
  }
}).observe({type: 'layout-shift', buffered: true});

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

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

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

Следующий код берет список записей layout-shift , которые внесли вклад в CLS, и возвращает самый большой исходный элемент из самого большого сдвига:

function getCLSDebugTarget(entries) {
  const largestEntry = entries.reduce((a, b) => {
    return a && a.value > b.value ? a : b;
  });
  if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
    const largestSource = largestEntry.sources.reduce((a, b) => {
      return a.node && a.previousRect.width * a.previousRect.height >
          b.previousRect.width * b.previousRect.height ? a : b;
    });
    if (largestSource) {
      return largestSource.node;
    }
  }
}

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

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

После того как вы определили и устранили основную причину изменений для этих элементов, ваш аналитический код начнет сообщать о небольших изменениях как о «худших» изменениях для ваших страниц. В конце концов, все зарегистрированные изменения будут достаточно малы, чтобы ваши страницы находились в пределах «хорошего» порога 0,1 !

Некоторые другие метаданные, которые может быть полезно захватить вместе с самым большим исходным элементом сдвига:

  • Время наибольшего сдвига
  • Путь URL-адреса на момент наибольшего сдвига (для сайтов, которые динамически обновляют URL-адрес, например одностраничных приложений).

Самая большая содержательная краска (LCP)

Для отладки LCP в полевых условиях основная информация, которая вам нужна, — это то, какой конкретный элемент был самым большим элементом (элементом-кандидатом LCP) для этой конкретной загрузки страницы.

Обратите внимание, что вполне возможно (на самом деле это довольно часто), что элемент-кандидат LCP будет отличаться от пользователя к пользователю, даже для одной и той же страницы.

Это может произойти по нескольким причинам:

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

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

Определите элемент-кандидат LCP

Чтобы определить элемент-кандидат LCP в JavaScript, вы можете использовать API Largest Contentful Paint — тот же API, который вы используете для определения значения времени LCP.

Наблюдая за записями largest-contentful-paint , вы можете определить текущий элемент-кандидат LCP, просматривая свойство element последней записи:

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});

Как только вы узнаете элемент-кандидат LCP, вы можете отправить его в свой аналитический инструмент вместе со значением метрики. Как и в случае с CLS, это поможет вам определить, какие элементы наиболее важно оптимизировать в первую очередь.

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

Взаимодействие со следующей отрисовкой (INP)

Наиболее важной информацией, которую необходимо получить в полевых условиях для INP, являются:

  1. С каким элементом взаимодействовал
  2. Почему это был тип взаимодействия
  3. Когда произошло это взаимодействие

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

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

Следующий код регистрирует целевой элемент и время записи INP.

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

Обратите внимание: этот код не показывает, как определить, какая запись event является записью INP, поскольку эта логика более сложна. Однако в следующем разделе объясняется, как получить эту информацию с помощью библиотеки JavaScript web-vitals .

Использование с библиотекой JavaScript web-vitals

В предыдущих разделах представлены некоторые общие рекомендации и примеры кода для сбора отладочной информации и включения ее в данные, отправляемые в инструмент аналитики.

Начиная с версии 3, библиотека JavaScript web-vitals включает в себя сборку атрибуции , которая отображает всю эту информацию, а также несколько дополнительных сигналов .

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

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'CLS':
      eventParams.debug_target = attribution.largestShiftTarget;
      break;
    case 'LCP':
      eventParams.debug_target = attribution.element;
      break;
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Этот код специфичен для Google Analytics, но общая идея должна быть применима и к другим инструментам аналитики.

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

Например, для отладки INP вам может потребоваться собрать элемент, с которым взаимодействует, тип взаимодействия, время, loadState, фазы взаимодействия и многое другое (например, данные длинного кадра анимации ).

Сборка атрибуции web-vitals предоставляет дополнительную информацию об атрибуции, как показано в следующем примере для INP:

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      break;

    // Additional metric logic...
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Полный список предоставляемых сигналов отладки см. в документации по атрибуции веб-виталов .

Составляйте отчеты и визуализируйте данные

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

Как упоминалось ранее, вам не обязательно решать каждую отдельную проблему, с которой сталкиваются ваши пользователи, вы хотите решить (особенно на первых порах) проблемы, которые затрагивают наибольшее количество пользователей, которые также должны быть проблемами, которые имеют наибольшее количество проблем. негативное влияние на ваши показатели Core Web Vitals.

Для GA4 см. специальную статью о том , как запрашивать и визуализировать данные с помощью BigQuery .

Краткое содержание

Надеемся, что этот пост помог обрисовать конкретные способы использования существующих API-интерфейсов производительности и библиотеки web-vitals для получения отладочной информации, которая поможет диагностировать производительность на основе посещений реальных пользователей на местах. Хотя это руководство сосредоточено на основных веб-показателях, эти концепции также применимы к отладке любых показателей производительности, которые можно измерить с помощью JavaScript.

Если вы только начинаете измерять производительность и уже являетесь пользователем Google Analytics, инструмент Web Vitals Report может быть хорошим местом для начала, поскольку он уже поддерживает отчеты об отладочной информации для показателей Core Web Vitals.

Если вы являетесь поставщиком аналитических услуг и хотите улучшить свои продукты и предоставить пользователям больше информации для отладки, рассмотрите некоторые из описанных здесь методов, но не ограничивайте себя только идеями, представленными здесь. Этот пост предназначен для общего применения ко всем инструментам аналитики; однако отдельные инструменты аналитики, вероятно, могут (и должны) собирать и сообщать еще больше отладочной информации.

Наконец, если вы чувствуете, что у вас есть пробелы в отладке этих показателей из-за отсутствия функций или информации в самих API, отправьте свой отзыв по адресу web-vitals-feedback@googlegroups.com .