[Перевод] Как отслеживать производительность веб-приложения с JavaScript и Performance API
Цель такой функции – иметь возможность ориентироваться на проекты, работая с которыми пользователи сталкиваются с длительной загрузкой, чтобы оптимизировать конфигурацию своего интерфейса. Это делает навигацию и взаимодействие с приложением плавнее и, таким образом, улучшает взаимодействие с пользователем. Для этого первым делом нужно выяснить, как мы собираемся реализовать такую функцию.
В зависимости от используемой среды разработки надстройки могут уже быть установлены. Если вы разработчик React, например, react-addons-per.
должен позволить вам отслеживать то, что вы хотите. В Forest Admin мы используем Ember.js, и нет никакой надстройки, подобной React. Поэтому воспользуемся Performance API, который, согласно документации, должен позволить нам сделать именно то, что мы хотим сделать:
Стандарт High Resolution Time определяет интерфейс производительности, который поддерживает измерения задержки на стороне клиента в приложениях. Интерфейсы Performance считаются интерфейсами с высоким разрешением, поскольку имеют точность до тысячных долей миллисекунды (в зависимости от аппаратных или программных ограничений).
II. API Performance
Performance API использует множество разнообразных методов. Нам понадобится всего 5:
-
mark
; -
measure
; -
getEntriesByType
; -
clearMarks/clearMeasures
.
1. mark
Метод mark
позволяет разместить маркер времени. Чтобы сослаться на маркер, требуется только один аргумент (строка), этот метод ничего не возвращает. Позже он позволит рассчитать время.
performance.mark('start');
2. measure
Метод measure
позволяет измерить разницу во времени между двумя маркерами. Он принимает 3 аргумента: имя созданного измерителя (строка), маркер начала (строка), маркер конца (строка). Этот метод возвращает объект со свойством duration
, которое вычисляет разницу между двумя маркерами.
async function timeDuration() {
performance.mark('start');
await new Promise(resolve => setTimeout(resolve, 100))
performance.mark('end');
return performance.measure('time', 'start', 'end').duration;
}
timeDuration().then((result) => console.log(result));
// output: 100
3. getEntriesByType
Метод getEntriesByType
позволяет получить доступ ко всем созданным объектам определённого типа. Он возвращает массив объектов и принимает в качестве аргумента тип входных значений (строку) из следующих: frame
, navigation
, resource
, mark
, measure
, paint
, longtask
. Не волнуйтесь, нам понадобятся только mark
и measure
.
performance.getEntriesByType('measure');
// output: return an Array of Object containing all the measure
4. clearMarks/clearMeasures
Методы clearMarks/clearMeasures используются для удаления ранее добавленных маркеров и измерителей из кеша браузера. Эти методы ничего не возвращают и не принимают никаких аргументов.
III. Давайте углубимся в код
Теперь, когда мы знаем методы реализации функциональности, нам нужно интегрировать её в код. У нас есть два варианта: создать маркеры и проводить измерения прямо в нужных местах кода или создать сервис (time-tracker.js
) и вставить его в код. Для наглядности выберем второй вариант.
performance.mark('start');
performance.mark('end');
performance.measure('time_duration', 'start', 'end');
console.log(performance.getEntriesByType('mark').length);
// output: 2
console.log(performance.getEntriesByType('measure').length);
// output: 1
performance.clearMarks();
performance.clearMeasures();
console.log(performance.getEntriesByType('mark').length);
// output: 0
console.log(performance.getEntriesByType('measure').length);
// output: 0
Всё просто, правда? Теперь нам нужно вызвать сервисные функции в тех местах кода, которые позволят нам отслеживать время загрузки запроса и интерфейса. Для интерфейса маркер timinginterfacestart
должен вызываться в начале загрузки страницы. Первым вызывается метод model
маршрута, который разместим здесь. Также возможно использовать методы в жизненных циклах компонента или любой другой функции, вызванной изначально. Однако следует соблюдать осторожность при размещении маркера. Если маркер не поставить в нужное место, последующее измерение будет неточным.
import { inject as service } from '@ember/service';
export default class RouteExample extends Route {
@service timeTracker;
model() {
this.timeTracker.startInterface();
// do something
}
}
Для маркера timinginterfacestop
он должен вызываться, когда закончен рендеринг приложения. Что касается рендеринга нескольких компонентов, логичным способом является использование методов в жизненных циклах этих компонентов. Метод компонента didRender
из ember кажется хорошим кандидатом. Затем идёт измерение общего времени загрузки интерфейса. Его можно разместить после маркера timinginterfacestop
или в любом другом желаемом месте.
import { inject as service } from '@ember/service';
export default class RenderingTracker extends Component {
@service timeTracker;
didRender() {
this.timeTracker.stopInterface();
}
stopInterfaceTracking() {
return this.timeTracker.measureTimingInterface()
}
}
Для расчёта времени запроса на сервере пользователя достаточно окружить функцию, отвечающую за запрос сервера пользователя, маркерами timingrequeststart
и Timingrequeststop
. Затем можно измерить время запроса, вызвав метод measureTimingRequest()
из нашего сервиса.
import { inject as service } from '@ember/service';
export default class RouteExample extends Route {
@service timeTracker;
model() {
this.timeTracker.startInterface();
// do something
}
async function fetchData(params) {
//do something
this.timeTracker.startRequest();
const records = await fetchRecords(params);
this.timingTracker.stopRequest();
const timingRequest = this.timingTracker.measureTimingRequest()
// do something else
}
}
Заключение
Надеюсь, вам понравилась эта статья. Есть и другие возможности реализовать эту функцию. Я решил показать вам путь, который имеет для меня больше смысла. API Performance – мощный инструмент, чтобы получить информацию о производительности вашего приложения. Важно знать, сталкиваются ли пользователи с трудностями, когда просматривают ваше приложение. Более того, это позволяет вам заранее нацеливаться на проблемы, чтобы решать эти проблемы и улучшать взаимодействие с пользователем. Следующим шагом может быть интеграция дополнительного электронного письма для пользователей, время загрузки у которых превышает пороговое значение, чтобы эти пользователи могли выбрать определённые параметры оптимизации.
КУРСЫ