Библиотека Web Vitals предоставляет набор инструментов для измерения ключевых метрик производительности веб-страниц, таких как Largest Contentful Paint (LCP), First Input Delay (FID), Cumulative Layout Shift (CLS) и другие. Каждая метрика отслеживается через callback-функции, передаваемые в API библиотеки. Правильная типизация этих функций является критически важной для стабильной интеграции в проекты на TypeScript и для предотвращения ошибок при обработке данных метрик.
Callback-функции в Web Vitals принимают один объект, содержащий информацию о метрике. Структура этого объекта определяется интерфейсами TypeScript, предоставляемыми библиотекой. Все метрики имеют общие поля:
name — название метрики
('LCP' | 'FID' | 'CLS' | ...).value — числовое значение метрики.delta — изменение значения метрики с предыдущего
измерения.id — уникальный идентификатор измерения.entries — массив объектов PerformanceEntry, относящихся
к данной метрике (не всегда присутствует).import { Metric } from 'web-vitals';
function handleMetric(metric: Metric) {
console.log(metric.name, metric.value, metric.delta);
}
В TypeScript интерфейс Metric выглядит следующим
образом:
export interface Metric {
name: string;
value: number;
delta: number;
id: string;
entries?: PerformanceEntry[];
}
Использование строгой типизации позволяет IDE подсказывать свойства метрики, предотвращает опечатки и делает код самодокументированным.
Каждая метрика имеет свои нюансы в типизации и поведении callback-функции.
Largest Contentful Paint (LCP)
(metric: Metric) => voidentries содержит массив объектов
LargestContentfulPaintEntry.import { getLCP, LCPMetric } from 'web-vitals';
function handleLCP(metric: LCPMetric) {
console.log(`LCP: ${metric.value}ms`);
console.log(`Элемент:`, metric.entries?.[0]?.element);
}
getLCP(handleLCP);
Интерфейс LCPMetric расширяет Metric и
уточняет тип entries:
export interface LCPMetric extends Metric {
entries?: Array<LargestContentfulPaintEntry>;
}
First Input Delay (FID)
(metric: Metric) => voidentries содержит EventTiming объекты,
связанные с первым пользовательским взаимодействием.import { getFID, FIDMetric } from 'web-vitals';
function handleFID(metric: FIDMetric) {
console.log(`FID: ${metric.value}ms`);
console.log(`Событие:`, metric.entries?.[0]?.name);
}
getFID(handleFID);
Cumulative Layout Shift (CLS)
(metric: Metric) => voidentries с
LayoutShift событиями.import { getCLS, CLSMetric } from 'web-vitals';
function handleCLS(metric: CLSMetric) {
console.log(`CLS: ${metric.value}`);
if (metric.entries) {
metric.entries.forEach(entry => {
console.log(`Смещение: ${entry.value}, источник:`, entry.sources);
});
}
}
getCLS(handleCLS);
Для удобства и переиспользования можно определить универсальный тип callback:
type WebVitalsCallback<T extends Metric = Metric> = (metric: T) => void;
Это позволяет строго типизировать функцию под конкретную метрику:
const logLCP: WebVitalsCallback<LCPMetric> = metric => {
console.log(metric.value);
};
type CoreMetric = LCPMetric | FIDMetric | CLSMetric;
function handleCoreMetric(metric: CoreMetric) {
switch (metric.name) {
case 'LCP':
console.log('LCP value:', metric.value);
break;
case 'FID':
console.log('FID value:', metric.value);
break;
case 'CLS':
console.log('CLS value:', metric.value);
break;
}
}
function sendToAnalytics<T extends Metric>(metric: T) {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify({
metricName: metric.name,
metricValue: metric.value,
metricDelta: metric.delta
})
});
}
Metric, LCPMetric, FIDMetric,
CLSMetric) для строгой типизации.entries перед обращением к
его элементам.Типизация callback-функций Web Vitals повышает безопасность кода, улучшает автодополнение в IDE и облегчает интеграцию метрик в аналитические системы, предотвращая ошибки на этапе компиляции.