Real User Monitoring (RUM) — это сбор и анализ данных о фактическом поведении пользователей в реальном времени. В веб-приложениях на Lit RUM используется для измерения производительности, стабильности и пользовательского опыта непосредственно в браузере, а не в лабораторных условиях. Такой подход позволяет фиксировать реальные задержки рендеринга, проблемы с сетью, ошибки выполнения и особенности взаимодействия с интерфейсом.
Lit, как библиотека для создания легковесных веб-компонентов, хорошо подходит для внедрения RUM благодаря чёткой модели жизненного цикла, реактивности и изоляции компонентов.
В приложениях на Lit чаще всего собираются следующие группы метрик:
firstUpdated).update /
updated).Lit не предоставляет встроенного RUM-механизма, поэтому используются стандартные Web API:
Используется для сбора таймингов:
performance.getEntriesByType('navigation')performance.getEntriesByType('paint')PerformanceObserver для LCP, CLS, INPwindow.onerrorwindow.addEventListener('error')window.addEventListener('unhandledrejection')Позволяет учитывать тип соединения и его качество.
На уровне приложения создаётся отдельный модуль, отвечающий за:
Этот слой не должен зависеть от конкретных компонентов.
export const rum = {
send(event) {
navigator.sendBeacon('/rum', JSON.stringify(event));
}
};
Lit предоставляет чёткие хуки, которые удобно использовать для RUM.
class UserCard extends LitElement {
connectedCallback() {
this._connectedAt = performance.now();
super.connectedCallback();
}
firstUpdated() {
const duration = performance.now() - this._connectedAt;
rum.send({
type: 'component-init',
name: 'user-card',
duration
});
}
}
updated(changedProps) {
rum.send({
type: 'component-update',
name: 'user-card',
props: [...changedProps.keys()]
});
}
Каждое изменение реактивного свойства вызывает обновление шаблона. В контексте RUM важно:
performUpdate() {
const start = performance.now();
super.performUpdate();
const duration = performance.now() - start;
if (duration > 16) {
rum.send({
type: 'slow-update',
component: this.tagName.toLowerCase(),
duration
});
}
}
Большинство компонентов Lit работают с асинхронными данными. Для RUM важно измерять:
async loadData() {
const start = performance.now();
const data = await fetch('/api/user').then(r => r.json());
this.user = data;
rum.send({
type: 'data-load',
component: 'user-card',
duration: performance.now() - start
});
}
RUM фиксирует не только технические, но и поведенческие данные:
В Lit это делается через обработчики событий.
handleClick() {
rum.send({
type: 'interaction',
component: 'user-card',
action: 'click'
});
}
Ошибки в шаблонах и методах компонентов особенно критичны, так как могут нарушить изоляцию UI.
try {
this.render();
} catch (e) {
rum.send({
type: 'component-error',
component: 'user-card',
message: e.message,
stack: e.stack
});
}
Для анализа RUM-данных необходим контекст:
Контекст добавляется централизованно при отправке данных.
rum.send({
type: 'metric',
name: 'LCP',
value,
context: {
sessionId,
appVersion,
locale
}
});
RUM не должен ухудшать производительность приложения. Применяются:
sendBeacon,visibilitychange.Грамотно внедрённый RUM:
Lit с его декларативностью и прозрачным жизненным циклом позволяет внедрять Real User Monitoring без жёсткого вмешательства в бизнес-логику, сохраняя читаемость и поддержку кода.