Одним из наиболее значительных преимуществ сервисных работников (по крайней мере, с точки зрения производительности) является их способность активно контролировать кэширование ресурсов. Веб-приложение, которое может кэшировать все необходимые ресурсы, должно загружаться значительно быстрее для постоянных посетителей. Но как эти преимущества на самом деле выглядят для реальных пользователей? И как это вообще измерить?
Веб-приложение Google I/O (сокращенно IOWA) — это прогрессивное веб-приложение , которое использовало большинство новых возможностей, предлагаемых сервисными работниками, для предоставления своим пользователям богатого опыта, подобного приложению. Компания также использовала Google Analytics для сбора ключевых данных о производительности и моделях использования своей большой и разнообразной аудитории пользователей.
В этом тематическом исследовании показано, как IOWA использовала Google Analytics, чтобы ответить на ключевые вопросы производительности и составить отчет о реальном влиянии работников сферы обслуживания.
Начиная с вопросов
Каждый раз, когда вы внедряете аналитику на веб-сайте или в приложении, важно начинать с определения вопросов, на которые вы пытаетесь ответить, исходя из данных, которые вы будете собирать.
Хотя у нас было несколько вопросов, на которые мы хотели ответить, для целей данного тематического исследования давайте сосредоточимся на двух наиболее интересных из них.
1. Является ли кэширование Service Worker более производительным, чем существующие механизмы кэширования HTTP, доступные во всех браузерах?
Мы уже ожидаем, что страницы для вернувшихся посетителей будут загружаться быстрее, чем для новых, поскольку браузеры могут кэшировать запросы и мгновенно обслуживать их при повторных посещениях.
Service Workers предлагает альтернативные возможности кэширования, которые дают разработчикам детальный контроль над тем, что именно и как выполняется кеширование. В IOWA мы оптимизировали реализацию сервис-воркера так, чтобы каждый ресурс кэшировался, чтобы вернувшиеся посетители могли использовать приложение полностью в автономном режиме.
Но будут ли эти усилия лучше, чем то, что браузер уже делает по умолчанию? И если да, то насколько лучше? 1
2. Как сервис-воркер влияет на загрузку сайта?
Другими словами, насколько быстро загружается сайт, независимо от фактического времени загрузки, измеряемого традиционными показателями загрузки страницы?
Ответить на вопросы о том, как ощущается опыт, очевидно, непростая задача, и ни один показатель не сможет идеально отразить такое субъективное мнение. При этом определенно есть некоторые показатели, которые лучше других, поэтому важно выбрать правильные.
Выбор правильной метрики
Google Analytics по умолчанию отслеживает время загрузки страниц (через API синхронизации навигации ) для 1% посетителей сайта и делает эти данные доступными с помощью таких показателей, как Avg. Время загрузки страницы.
Среднее Время загрузки страницы — хороший показатель для ответа на наш первый вопрос, но не особенно хороший показатель для ответа на второй. Во-первых, событие load
не обязательно соответствует моменту, когда пользователь может фактически взаимодействовать с приложением. Более того, может показаться , что два приложения с одинаковым временем загрузки загружаются по-разному. Например, сайт с заставкой или индикатором загрузки, вероятно, будет загружаться намного быстрее, чем сайт, который просто показывает пустую страницу в течение нескольких секунд.
В IOWA мы показали анимацию обратного отсчета на заставке, которая (на мой взгляд) очень успешно развлекала пользователя, пока остальная часть приложения загружалась в фоновом режиме. По этой причине отслеживание времени появления заставки имеет гораздо больше смысла как способ измерения воспринимаемой производительности нагрузки. Чтобы получить это значение, мы выбрали метрику времени первой отрисовки .
Как только мы определились с вопросами, на которые хотим ответить, и определили показатели, которые будут полезны при ответе на них, пришло время внедрить Google Analytics и начать проводить измерения.
Реализация аналитики
Если вы раньше использовали Google Analytics, то вы, вероятно, знакомы с рекомендуемым фрагментом отслеживания JavaScript. Это выглядит так:
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
Первая строка приведенного выше кода инициализирует глобальную функцию ga()
(если она еще не существует), а последняя строка асинхронно загружает библиотеку analytics.js
.
Средняя часть содержит эти две строки:
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
Эти две команды отслеживают, какие страницы посещают люди, заходящие на ваш сайт, но не более того . Если вы хотите отслеживать дополнительные взаимодействия с пользователем, вам придется делать это самостоятельно.
Что касается IOWA, мы хотели отслеживать еще две вещи:
- Время, прошедшее между первой загрузкой страницы и появлением пикселей на экране.
- Независимо от того, контролирует ли сервисный работник страницу. Имея эту информацию, мы могли сегментировать наши отчеты, чтобы сравнить результаты с использованием Service Worker и без него.
Запечатлеть время первой покраски
Некоторые браузеры записывают точное время появления на экране первого пикселя и предоставляют это время разработчикам. Это значение в сравнении со значением navigationStart
, предоставленным через API синхронизации навигации, дает нам очень точный учет того, сколько времени прошло между моментом, когда пользователь первоначально запросил страницу, и тем, когда он впервые что-то увидел.
Как я уже упоминал, время первой отрисовки — важный показатель для измерения, поскольку это первая точка, в которой пользователь ощущает скорость загрузки вашего сайта. Это первое впечатление, которое получают пользователи, и хорошее первое впечатление может положительно повлиять на остальную часть пользовательского опыта. 2
Чтобы получить первое значение отрисовки в браузерах, которые его предоставляют, мы создали служебную функцию getTimeToFirstPaintIfSupported
:
function getTimeToFirstPaintIfSupported() {
// Ignores browsers that don't support the Performance Timing API.
if (window.performance && window.performance.timing) {
var navTiming = window.performance.timing;
var navStart = navTiming.navigationStart;
var fpTime;
// If chrome, get first paint time from `chrome.loadTimes`.
if (window.chrome && window.chrome.loadTimes) {
fpTime = window.chrome.loadTimes().firstPaintTime * 1000;
}
// If IE/Edge, use the prefixed `msFirstPaint` property.
// See http://msdn.microsoft.com/ff974719
else if (navTiming.msFirstPaint) {
fpTime = navTiming.msFirstPaint;
}
if (fpTime && navStart) {
return fpTime - navStart;
}
}
}
Благодаря этому мы теперь могли бы написать еще одну функцию, которая отправляет событие отсутствия взаимодействия со временем первой отрисовки в качестве значения: 3
function sendTimeToFirstPaint() {
var timeToFirstPaint = getTimeToFirstPaintIfSupported();
if (timeToFirstPaint) {
ga('send', 'event', {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true
});
}
}
После написания обеих этих функций наш код отслеживания будет выглядеть следующим образом:
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
Обратите внимание, что в зависимости от того, когда выполняется приведенный выше код, пиксели могут быть уже нарисованы на экране, а могут и не быть. Чтобы гарантировать, что мы всегда запускаем этот код после первой отрисовки, мы отложили вызов sendTimeToFirstPaint()
до события load
. Фактически, мы решили отложить отправку всех аналитических данных до загрузки страницы, чтобы гарантировать, что эти запросы не будут конкурировать с загрузкой других ресурсов.
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
});
Код выше сообщает Google Analytics о времени firstpaint
, но это только половина дела. Нам все еще нужно было отслеживать статус сервис-воркера; в противном случае мы не смогли бы сравнить время первой отрисовки страницы, контролируемой сервисным работником, и неконтролируемой страницы.
Определение статуса сервисного работника
Чтобы определить текущий статус сервис-воркера, мы создали служебную функцию, которая возвращает одно из трех значений:
- контролируемый : сервисный работник контролирует страницу. В случае с IOWA это также означает, что все ресурсы кэшированы и страница работает в автономном режиме.
- поддерживается : браузер поддерживает сервис-воркера, но сервис-воркер еще не управляет страницей. Это ожидаемый статус для посетителей, впервые посещающих сайт.
- неподдерживаемый : браузер пользователя не поддерживает Service Worker.
function getServiceWorkerStatus() {
if ('serviceWorker' in navigator) {
return navigator.serviceWorker.controller ? 'controlled' : 'supported';
} else {
return 'unsupported';
}
}
Эта функция получила для нас статус сервис-воркера; Следующим шагом было связать этот статус с данными, которые мы отправляли в Google Analytics.
Отслеживание пользовательских данных с помощью пользовательских параметров
По умолчанию Google Analytics предоставляет вам множество способов разделить общий трафик на группы на основе атрибутов пользователя, сеанса или взаимодействия. Эти атрибуты известны как измерения . Общие параметры, которые волнуют веб-разработчиков, — это такие вещи, как браузер , операционная система или категория устройства .
Статус сервисного работника не является параметром, который Google Analytics предоставляет по умолчанию; однако Google Analytics дает вам возможность создавать собственные параметры и определять их по своему усмотрению.
Для IOWA мы создали специальный параметр под названием «Статус Service Worker» и установили его область действия на попадание (т. е. на каждое взаимодействие). 4. Каждому специальному параметру, который вы создаете в Google Analytics, присваивается уникальный индекс внутри этого свойства, и в коде отслеживания вы можете ссылаться на этот параметр по его индексу. Например, если бы индекс только что созданного измерения был равен 1, мы могли бы обновить нашу логику следующим образом, чтобы отправить событие firstpaint
, включив в него статус сервисного работника:
ga('send', 'event', {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true,
// Sets the current service worker status as the value of
// `dimension1` for this event.
dimension1: getServiceWorkerStatus()
});
Это работает, но статус сервисного работника будет ассоциироваться только с этим конкретным событием. Поскольку статус Service Worker потенциально полезен при любом взаимодействии, лучше всего включать его во все данные, отправляемые в Google Analytics.
Чтобы включить эту информацию во все обращения (например, все просмотры страниц, события и т. д.), мы устанавливаем значение специального параметра в самом объекте отслеживания перед отправкой каких-либо данных в Google Analytics.
ga('set', 'dimension1', getServiceWorkerStatus());
После установки это значение отправляется со всеми последующими обращениями для текущей загрузки страницы. Если позже пользователь снова загрузит страницу, функция getServiceWorkerStatus()
скорее всего, вернет новое значение, и это значение будет установлено в объекте трекера.
Небольшое замечание о ясности и читаемости кода: поскольку другие люди, просматривающие этот код, могут не знать, к чему относится dimension1
, всегда лучше создать переменную, которая сопоставляет осмысленные имена измерений со значениями, которые будет использовать Analytics.js.
// Creates a map between custom dimension names and their index.
// This is particularly useful if you define lots of custom dimensions.
var customDimensions = {
SERVICE_WORKER_STATUS: 'dimension1'
};
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Sets the service worker status on the tracker,
// so its value is included in all future hits.
ga('set', customDimensions.SERVICE_WORKER_STATUS, getServiceWorkerStatus());
// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
});
Как я уже упоминал, отправка измерения «Статус Service Worker» при каждом обращении позволяет нам использовать его при составлении отчетов по любой метрике.
Как видите, почти 85% всех просмотров страниц IOWA были осуществлены из браузеров, поддерживающих Service Worker .
Результаты: отвечаем на наши вопросы
Как только мы начали собирать данные для ответа на наши вопросы, мы могли сообщить об этих данных, чтобы увидеть результаты. (Примечание: все показанные здесь данные Google Analytics представляют собой фактический веб-трафик сайта IOWA за период с 16 по 22 мая 2016 г.).
Первый вопрос, который у нас возник: является ли кэширование Service Worker более производительным, чем существующие механизмы кэширования HTTP, доступные во всех браузерах?
Чтобы ответить на этот вопрос, мы создали специальный отчет , в котором учитывается показатель Avg. Время загрузки страницы в различных измерениях. Эта метрика хорошо подходит для ответа на этот вопрос, поскольку событие load
срабатывает только после загрузки всех начальных ресурсов. Таким образом, оно напрямую отражает общее время загрузки всех критически важных ресурсов сайта. 5
Размеры, которые мы выбрали:
- Наше индивидуальное измерение «Статус сервисного работника» .
- Тип пользователя , который указывает, является ли это первым посещением сайта пользователем или он возвращается. (Примечание: у нового посетителя не будет кэшированных ресурсов; у вернувшегося посетителя могут быть кэшированные ресурсы.)
- Категория устройства , которая позволяет нам сравнивать результаты на мобильных устройствах и настольных компьютерах.
Чтобы исключить возможность того, что факторы, не связанные с Service Worker, искажают результаты времени загрузки, мы ограничили наш запрос, включив в него только браузеры, поддерживающие Service Worker.
Как видите, посещения нашего приложения, контролируемые сервисным работником, загружались немного быстрее, чем неконтролируемые посещения, даже те, которые совершались вернувшимися пользователями, у которых, вероятно, была кэширована большая часть ресурсов страницы. Также интересно отметить, что в среднем посетители с мобильных устройств с сервис-воркером загружались быстрее, чем посетители с настольных компьютеров.
«…посещения нашего приложения, контролируемые сервисным работником, загружаются немного быстрее, чем неконтролируемые посещения…»
Более подробную информацию вы можете увидеть в следующих двух таблицах:
Среднее Время загрузки страницы (рабочий стол) | |||
---|---|---|---|
Статус сервисного работника | Тип пользователя | Среднее Время загрузки страницы (мс) | Размер образца |
Контролируемый | Возвращающийся посетитель | 2568 | 30860 |
Поддерживается | Возвращающийся посетитель | 3612 | 1289 |
Поддерживается | Новый посетитель | 4664 | 21991 |
Среднее Время загрузки страницы (мобильное устройство) | |||
---|---|---|---|
Статус сервисного работника | Тип пользователя | Среднее Время загрузки страницы (мс) | Размер образца |
Контролируемый | Возвращающийся посетитель | 3760 | 8162 |
Поддерживается | Возвращающийся посетитель | 4843 | 676 |
Поддерживается | Новый посетитель | 6158 | 5779 |
Вам может быть интересно, как это возможно, чтобы вернувшийся посетитель, чей браузер поддерживает Service Worker, когда-либо находился в неконтролируемом состоянии. Этому есть несколько возможных объяснений:
- Пользователь покинул страницу при первом посещении до того, как работник службы успел завершить инициализацию.
- Пользователь удалил сервисного работника с помощью инструментов разработчика.
Обе эти ситуации относительно редки. Мы можем увидеть это в данных, посмотрев на значения образца загрузки страницы в четвертом столбце. Обратите внимание, что средние строки содержат гораздо меньшую выборку, чем две другие.
Наш второй вопрос был: как сервис-воркер влияет на загрузку сайта?
Чтобы ответить на этот вопрос, мы создали еще один специальный отчет для метрики Avg. Event Value и отфильтровал результаты, чтобы включить только наши события firstpaint
. Мы использовали измерения «Категория устройства» и наше собственное измерение «Статус сервисного работника» .
Вопреки моим ожиданиям, сервис-воркер на мобильных устройствах оказал гораздо меньшее влияние на время первой отрисовки, чем на общую загрузку страницы.
«…Service Worker на мобильных устройствах оказал гораздо меньшее влияние на время первой отрисовки, чем на общую загрузку страницы».
Чтобы понять, почему это так, нам нужно углубиться в данные. Средние значения могут быть хороши для общего обзора и общих черт, но чтобы по-настоящему понять, как эти цифры распределяются по разным пользователям, нам нужно посмотреть на распределение времени firstpaint
.
Получение распределения метрики в Google Analytics
Чтобы получить распределение времени firstpaint
, нам нужен доступ к отдельным результатам для каждого события. К сожалению, Google Analytics не упрощает эту задачу.
Google Analytics позволяет нам разбить отчет по любому измерению, которое мы хотим, но не позволяет разбивать отчет по показателям. Это не значит, что это невозможно, это просто означает, что нам пришлось еще немного настроить нашу реализацию, чтобы получить желаемый результат.
Поскольку результаты отчета можно разбить только по измерениям, нам пришлось установить значение метрики (в данном случае время firstpaint
) в качестве специального измерения для события. Для этого мы создали еще один специальный параметр под названием «Значение показателя» и обновили логику отслеживания firstpaint
следующим образом:
var customDimensions = {
SERVICE_WORKER_STATUS: 'dimension1',
<strong>METRIC_VALUE: 'dimension2'</strong>
};
// ...
function sendTimeToFirstPaint() {
var timeToFirstPaint = getTimeToFirstPaintIfSupported();
if (timeToFirstPaint) {
var fields = {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true
}
<strong>// Sets the event value as a dimension to allow for breaking down the
// results by individual metric values at reporting time.
fields[customDimensions.METRIC_VALUE] = String(fields.eventValue);</strong>
ga('send', 'event', fields);
}
}
Веб-интерфейс Google Analytics в настоящее время не предоставляет возможности визуализировать распределение произвольных значений показателей, но с помощью API Google Analytics Core Reporting API и библиотеки Google Charts мы можем запросить необработанные результаты, а затем самостоятельно построить гистограмму.
Например, следующая конфигурация запроса API использовалась для получения распределения значений firstpaint
на рабочем столе с помощью неконтролируемого сервисного работника.
{
dateRanges: [{startDate: '2016-05-16', endDate: '2016-05-22'}],
metrics: [{expression: 'ga:totalEvents'}],
dimensions: [{name: 'ga:dimension2'}],
dimensionFilterClauses: [
{
operator: 'AND',
filters: [
{
dimensionName: 'ga:eventAction',
operator: 'EXACT',
expressions: ['firstpaint']
},
{
dimensionName: 'ga:dimension1',
operator: 'EXACT',
expressions: ['supported']
},
{
dimensionName: 'ga:deviceCategory',
operator: 'EXACT',
expressions: ['desktop']
}
],
}
],
orderBys: [
{
fieldName: 'ga:dimension2',
orderType: 'DIMENSION_AS_INTEGER'
}
]
}
Этот запрос API возвращает массив значений, которые выглядят следующим образом (Примечание: это только первые пять результатов). Результаты отсортированы от меньшего к большему, поэтому в этих строках указано самое быстрое время.
Результаты ответа API (первые пять строк) | |
---|---|
га: измерение2 | ga:totalEvents |
4 | 3 |
5 | 2 |
6 | 10 |
7 | 8 |
8 | 10 |
Вот что означают эти результаты на простом английском языке:
- Было 3 события, где значение
firstpaint
составляло 4 мс. - Было 2 события, где значение
firstpaint
составляло 5 мс. - Было 10 событий, где значение
firstpaint
составляло 6 мс. - Было 8 событий, где значение
firstpaint
составляло 7 мс. - Было 10 событий, где
value
firstpaint
составляло 8 мс. - и т. д.
На основании этих результатов мы можем экстраполировать значение firstpaint
для каждого отдельного события и построить гистограмму распределения. Мы сделали это для каждого из выполняемых нами запросов.
Вот как выглядел дистрибутив на десктопе с неконтролируемым (но поддерживаемым) сервис-воркером:
![Время первой отрисовки на рабочем столе (поддерживается)](https://web.dev/static/case-studies/service-worker-perf/image/time-first-paint-distrib-adc6d60d00c31.png?authuser=5&hl=ru)
Среднее время firstpaint
для приведенного выше распределения составляет 912 мс .
Форма этой кривой вполне типична для распределения нагрузки по времени. Сравните это с гистограммой ниже, которая показывает распределение событий первой отрисовки для посещений, при которых страницу контролировал работник службы.
![Время до первого распределения краски на рабочем столе (контролируется)](https://web.dev/static/case-studies/service-worker-perf/image/time-first-paint-distrib-0b74756b849ee.png?authuser=5&hl=ru)
Обратите внимание: когда сервисный работник контролировал страницу, у многих посетителей первая отрисовка происходила практически сразу, в среднем за 583 мс .
«…когда сервисный работник контролировал страницу, многие посетители почти сразу же почувствовали первую отрисовку…»
Чтобы лучше понять, как эти два распределения сравниваются друг с другом, на следующей диаграмме показано их объединенное представление. Гистограмма, показывающая неконтролируемые посещения обслуживающего персонала, накладывается поверх гистограммы, показывающей контролируемые посещения, и оба этих посещения накладываются поверх гистограммы, показывающей оба вместе взятых.
![Пришло время первого распространения рисования на рабочем столе](https://web.dev/static/case-studies/service-worker-perf/image/time-first-paint-distrib-5f69da3b18e2c.png?authuser=5&hl=ru)
В этих результатах мне показалось интересным то, что распределение с контролируемым сервис-воркером все еще имело колоколообразную кривую после первоначального всплеска. Я ожидал большого начального всплеска, а затем постепенного спада, я не ожидал второго пика кривой.
Когда я изучил, что может быть причиной этого, я узнал, что, хотя сервисный работник может управлять страницей, ее поток может быть неактивным. Браузер делает это для экономии ресурсов — очевидно, вам не нужно, чтобы каждый сервис-воркер для каждого сайта, который вы когда-либо посещали, был активен и готов в любой момент. Это объясняет хвост распределения. У некоторых пользователей произошла задержка при запуске потока сервисного работника.
Однако, как вы можете видеть из дистрибутива, даже с этой начальной задержкой браузеры с сервис-воркером доставляли контент быстрее, чем браузеры, проходящие через сеть.
Вот как все выглядело на мобильном телефоне:
![Время первого распространения рисунков на мобильных устройствах](https://web.dev/static/case-studies/service-worker-perf/image/time-first-paint-distrib-4ae7b2dd6775c.png?authuser=5&hl=ru)
Хотя у нас все еще было значительное увеличение времени первой покраски, хвост стал немного больше и длиннее. Вероятно, это связано с тем, что на мобильных устройствах запуск простоя рабочего потока службы занимает больше времени, чем на настольном компьютере. Это также объясняет, почему разница между средним временем firstpaint
оказалась не такой большой, как я ожидал (обсуждалось выше).
«…на мобильных устройствах запуск простоя рабочего потока службы занимает больше времени, чем на настольном компьютере».
Вот разбивка этих изменений среднего времени первой отрисовки на мобильных и настольных компьютерах, сгруппированных по статусу сервис-воркера:
Среднее время до первой краски (мс) | ||
---|---|---|
Статус сервисного работника | Рабочий стол | мобильный |
Контролируемый | 583 | 1634 г. |
Поддерживается (не контролируется) | 912 | 1933 год |
Хотя создание этих визуализаций распределения заняло немного больше времени и усилий, чем создание специального отчета в Google Analytics, они дают нам гораздо лучшее представление о том, как работники сферы обслуживания влияют на производительность нашего сайта, чем одни только средние показатели.
Другое влияние со стороны обслуживающего персонала
Помимо влияния на производительность, работники сферы обслуживания также влияют на взаимодействие с пользователем несколькими другими способами, которые можно измерить с помощью Google Analytics.
Оффлайн доступ
Сервис-воркеры позволяют пользователям взаимодействовать с вашим сайтом в автономном режиме, и хотя какая-то автономная поддержка, вероятно, имеет решающее значение для любого прогрессивного веб-приложения, определение того, насколько она важна в вашем случае, во многом зависит от того, насколько часто использование происходит в автономном режиме. Но как нам это измерить?
Для отправки данных в Google Analytics требуется подключение к Интернету, но не требуется, чтобы данные отправлялись в точное время, когда произошло взаимодействие. Google Analytics поддерживает отправку данных о взаимодействии постфактум, указав смещение времени (через параметр qt
).
В течение последних двух лет IOWA использует сценарий Service Worker , который обнаруживает неудачные обращения к Google Analytics, когда пользователь находится в автономном режиме, и воспроизводит их позже с помощью параметра qt
.
Чтобы отслеживать, был ли пользователь онлайн или оффлайн, мы создали настраиваемое измерение под названием Online и установили для него значение navigator.onLine
, затем мы прослушивали события online
и offline
и соответствующим образом обновляли измерение.
И чтобы понять, насколько часто пользователь находился в автономном режиме при использовании IOWA, мы создали сегмент , ориентированный на пользователей, совершивших хотя бы одно офлайн-взаимодействие. Оказывается, это было почти 5% пользователей.
Всплывающее уведомление
Сервисные работники позволяют пользователям соглашаться на получение push-уведомлений. В IOWA пользователи уведомлялись о начале сеанса в их расписании.
Как и в случае с любой формой уведомлений, важно найти баланс между тем, чтобы приносить пользу пользователю и раздражать его. Чтобы лучше понять, что происходит, важно отслеживать, соглашаются ли пользователи на получение этих уведомлений, взаимодействуют ли они с ними, когда они приходят, и не изменяют ли пользователи, которые ранее согласились на получение этих уведомлений, свои предпочтения и отказываются от них.
В IOWA мы отправляли только уведомления, связанные с персонализированным расписанием пользователя, которое могли создавать только вошедшие в систему пользователи. Это ограничило набор пользователей, которые могли получать уведомления, только вошедшими в систему пользователями (отслеживаемыми с помощью специального параметра под названием «Войти» ), чьи браузеры поддерживают push-уведомления (отслеживаемые с помощью другого специального параметра под названием « Разрешение на уведомление» ).
Следующий отчет основан на метрике «Пользователи» и нашем специальном параметре «Разрешение на уведомление», сегментированном по пользователям, которые в какой-то момент вошли в систему и чьи браузеры поддерживают push-уведомления.
Приятно видеть, что более половины наших вошедших в систему пользователей решили получать push-уведомления.
Баннеры установки приложения
Если веб-приложение Progress соответствует критериям и часто используется пользователем, этому пользователю может быть показан баннер установки приложения, предлагающий добавить приложение на главный экран.
В IOWA мы отслеживали, как часто эти подсказки отображались пользователю (и были ли они приняты) с помощью следующего кода:
window.addEventListener('beforeinstallprompt', function(event) {
// Tracks that the user saw a prompt.
ga('send', 'event', {
eventCategory: 'installprompt',
eventAction: 'fired'
});
event.userChoice.then(function(choiceResult) {
// Tracks the users choice.
ga('send', 'event', {
eventCategory: 'installprompt',
// `choiceResult.outcome` will be 'accepted' or 'dismissed'.
eventAction: choiceResult.outcome,
// `choiceResult.platform` will be 'web' or 'android' if the prompt was
// accepted, or '' if the prompt was dismissed.
eventLabel: choiceResult.platform
});
});
});
Из пользователей, увидевших баннер установки приложения, около 10% решили добавить его на свой главный экран.
Возможные улучшения отслеживания (в следующий раз)
Аналитические данные, которые мы собрали в IOWA в этом году, были неоценимы. Но ретроспективный взгляд всегда выявляет дыры и возможности улучшить ситуацию в следующий раз. После завершения анализа этого года, вот две вещи, которые мне хотелось бы сделать по-другому, но которые читатели, желающие реализовать аналогичную стратегию, возможно, захотят рассмотреть:
1. Отслеживайте больше событий, связанных с загрузкой.
Мы отслеживали несколько событий, которые соответствуют техническим показателям (например, HTMLImportsLoaded , WebComponentsReady и т. д.), но поскольку значительная часть нагрузки выполнялась асинхронно, момент, в котором эти события запускались, не обязательно соответствовал конкретному моменту в целом. опыт загрузки.
Основное событие, связанное с загрузкой, которое мы не отслеживали (но хотели бы это сделать), — это момент, когда заставка исчезает и пользователь может видеть содержимое страницы.
2. Сохраните идентификатор аналитического клиента в IndexedDB.
По умолчанию Analytics.js сохраняет поле идентификатора клиента в файлах cookie браузера; к сожалению, сценарии сервисных работников не могут получить доступ к файлам cookie.
Это представляло для нас проблему, когда мы пытались реализовать отслеживание уведомлений. Мы хотели отправлять событие от сервисного работника (через протокол измерений ) каждый раз, когда пользователю отправляется уведомление, а затем отслеживать успешность повторного взаимодействия с этим уведомлением, если пользователь нажимает на него и возвращается в приложение.
Хотя мы могли отслеживать успех уведомлений в целом с помощью параметра кампании utm_source
, мы не смогли привязать конкретный сеанс повторного вовлечения к конкретному пользователю.
Чтобы обойти это ограничение, мы могли бы сохранить идентификатор клиента через IndexedDB в нашем коде отслеживания, и тогда это значение было бы доступно сценарию сервисного работника.
3. Пусть сервисный работник сообщит о статусе онлайн/офлайн.
Проверка navigator.onLine
позволит вам узнать, может ли ваш браузер подключиться к маршрутизатору или локальной сети, но не обязательно скажет, есть ли у пользователя реальное подключение. А поскольку наш рабочий сценарий службы автономной аналитики просто воспроизводил неудачные обращения (не изменяя их и не отмечая их как неудачные), мы, вероятно, занижали данные об использовании в автономном режиме.
В будущем нам следует отслеживать как статус navigator.onLine
, так и то, было ли обращение воспроизведено сервис-воркером из-за первоначального сбоя сети. Это даст нам более точную картину реального использования в автономном режиме.
Подведение итогов
Этот практический пример показал, что использование Service Worker действительно улучшило производительность загрузки веб-приложения Google I/O в широком диапазоне браузеров, сетей и устройств. Также было показано, что, если вы посмотрите на распределение данных о нагрузке по широкому спектру браузеров, сетей и устройств, вы получите гораздо больше понимания того, как эта технология обрабатывает реальные сценарии, и обнаружите характеристики производительности, которые вы можете не ожидал.
Вот некоторые ключевые выводы исследования IOWA:
- В среднем страницы загружались немного быстрее, когда ими управлял сервис-воркер, чем без него, как для новых, так и для вернувшихся посетителей.
- Посещения страниц, контролируемых сервисным работником, для многих пользователей загружались практически мгновенно.
- Работникам службы, когда они неактивны, требуется некоторое время для запуска. Тем не менее, неактивный сервисный работник по-прежнему работал лучше, чем отсутствие сервисного работника.
- Время запуска неактивного сервис-воркера на мобильных устройствах было больше, чем на настольных компьютерах.
Хотя о приросте производительности, наблюдаемом в одном конкретном приложении, обычно полезно сообщить более широкому сообществу разработчиков, важно помнить, что эти результаты специфичны для типа сайта IOWA (сайт мероприятия) и типа аудитории IOWA (в основном Разработчики).
Если вы реализуете Service Worker в своем приложении, важно реализовать собственную стратегию измерения, чтобы вы могли оценить собственную производительность и предотвратить будущий регресс. Если да, поделитесь своими результатами, чтобы каждый мог получить пользу!
Сноски
- Не совсем справедливо сравнивать производительность нашей реализации кэша Service Worker с производительностью нашего сайта только с HTTP-кешем. Поскольку мы оптимизировали IOWA для сервис-воркера, мы не потратили много времени на оптимизацию HTTP-кэша. Если бы мы это сделали, результаты, вероятно, были бы другими. Чтобы узнать больше об оптимизации вашего сайта для кэша HTTP, прочитайте «Эффективная оптимизация контента» .
- В зависимости от того, как ваш сайт загружает стили и контент, возможно, браузер сможет рисовать до того, как контент или стили станут доступны. В таких случаях
firstpaint
может соответствовать пустому белому экрану. Если вы используетеfirstpaint
, важно убедиться, что он соответствует значимому моменту загрузки ресурсов вашего сайта. - Технически мы могли бы отправить временной удар (который по умолчанию не является взаимодействием), чтобы захватить эту информацию вместо события. Фактически, временные попадания были добавлены в Google Analytics специально для отслеживания таких показателей нагрузки; однако совпадения по времени тщательно выбираются во время обработки, и их значения нельзя использовать в сегментах . Учитывая эти текущие ограничения, события без взаимодействия остаются более подходящими.
- Чтобы лучше понять, какую область действия следует предоставить специальному параметру в Google Analytics, обратитесь к разделу «Пользовательский параметр» Справочного центра Google Analytics. Также важно понимать модель данных Google Analytics, которая состоит из пользователей, сеансов и взаимодействий (обращений). Чтобы узнать больше, посмотрите урок Analytics Academy, посвященный модели данных Google Analytics .
- Это не учитывает ресурсы, лениво загружаемые после события загрузки.