Web Vitals
Web Vitals — набор метрик Google для измерения пользовательского опыта: скорость загрузки, интерактивность и визуальная стабильность.
Зачем нужно
Google использует Web Vitals как фактор ранжирования. Но важнее другое: эти метрики напрямую влияют на конверсию. Каждая дополнительная секунда загрузки снижает конверсию. Web Vitals дают конкретные цифры для оптимизации.
Где используется
Все публичные веб-сайты. Измеряются через Lighthouse, PageSpeed Insights, Chrome DevTools, CrUX (Chrome User Experience Report), Google Search Console.
Предпосылки
HTML/CSS/JavaScript, базовое понимание HTTP
Core Web Vitals (3 главные метрики)
LCP — Largest Contentful Paint
Скорость загрузки. Время до отрисовки самого большого видимого элемента (изображение, заголовок, видео).
Хорошо: ≤ 2.5 секунды
Требует улучшения: 2.5–4.0 секунды
Плохо: > 4.0 секунды
Что считается LCP-элементом:
<img><video>(poster)- Элемент с
background-image - Блочный элемент с текстом
// Измерение LCP через Performance API
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries;
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime, 'ms');
console.log('LCP element:', lastEntry.element);
}).observe({ type: 'largest-contentful-paint', buffered: true });
Как улучшить LCP:
- Оптимизировать изображения (WebP, AVIF, srcset)
- Предзагрузка LCP-ресурса:
<link rel="preload"> - SSR или Static Generation вместо CSR
- CDN для статики
- Убрать render-blocking CSS/JS
INP — Interaction to Next Paint
Отзывчивость. Задержка между действием пользователя (клик, нажатие) и визуальным откликом. Заменил FID в 2024.
Хорошо: ≤ 200 мс
Требует улучшения: 200–500 мс
Плохо: > 500 мс
// Измерение INP
new PerformanceObserver((list) => {
for (const entry of list.getEntries) {
if (entry.interactionId) {
console.log('Interaction:', entry.name, entry.duration, 'ms');
}
}
}).observe({ type: 'event', buffered: true, durationThreshold: 16 });
Как улучшить INP:
- Разбить долгие задачи на маленькие (
setTimeout,requestIdleCallback) - Минимизировать JavaScript на главном потоке
- Использовать Web Workers для тяжёлых вычислений
content-visibility: autoдля невидимого контента
CLS — Cumulative Layout Shift
Визуальная стабильность. Сумма всех неожиданных сдвигов элементов на странице.
Хорошо: ≤ 0.1
Требует улучшения: 0.1–0.25
Плохо: > 0.25
// Измерение CLS
let clsValue = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
console.log('CLS:', clsValue);
}
}
}).observe({ type: 'layout-shift', buffered: true });
Как улучшить CLS:
- Задать
widthиheightдля изображений - Использовать
aspect-ratioCSS - Резервировать место для динамического контента
- Не вставлять контент выше текущего viewport
font-display: swapдля шрифтов
<!-- ПЛОХО: изображение без размеров — CLS при загрузке -->
<img src="photo.jpg">
<!-- ХОРОШО: размеры заданы — место зарезервировано -->
<img src="photo.jpg" width="800" height="600" loading="lazy">
<!-- ХОРОШО: через aspect-ratio -->
<img src="photo.jpg" style="aspect-ratio: 4/3; width: 100%;">
Дополнительные метрики
TTFB — Time to First Byte
Время от запроса до первого байта ответа. Отражает скорость сервера.
Хорошо: ≤ 800 мс
FCP — First Contentful Paint
Время до первого отрисованного контента (текст, изображение, SVG).
Хорошо: ≤ 1.8 секунды
Field Data vs Lab Data
| Field Data | Lab Data | |
|---|---|---|
| Источник | Реальные пользователи | Синтетический тест |
| Инструменты | CrUX, Google Search Console | Lighthouse, WebPageTest |
| Отражает | Реальный UX | Потенциальную проблему |
| INP | Да | Нет (только TBT) |
| Вариативность | Высокая (разные устройства) | Стабильная |
Измерение Web Vitals
web-vitals library
import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
console.log(metric.name, metric.value, metric.rating);
// Отправка в аналитику
navigator.sendBeacon('/analytics', JSON.stringify(metric));
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);
Chrome DevTools
1. F12 → Performance → Record → Выполни действия → Stop
2. Смотри: LCP, CLS, Long Tasks
3. Lighthouse tab → Generate Report
PageSpeed Insights
https://pagespeed.web.dev/
Показывает и Lab Data (Lighthouse), и Field Data (CrUX)
Целевые значения
| Метрика | Хорошо | Средне | Плохо |
|---|---|---|---|
| LCP | ≤ 2.5с | 2.5–4.0с | > 4.0с |
| INP | ≤ 200мс | 200–500мс | > 500мс |
| CLS | ≤ 0.1 | 0.1–0.25 | > 0.25 |
| FCP | ≤ 1.8с | 1.8–3.0с | > 3.0с |
| TTFB | ≤ 800мс | 800–1800мс | > 1800мс |
Частые ошибки
1. Оптимизация только Lab Data
Lighthouse показывает 100, но реальные пользователи жалуются.
Field Data учитывает медленные устройства и соединения.
Проверяй CrUX / Google Search Console.
2. Игнорирование CLS
<!-- Реклама, баннеры, lazy-loaded изображения без размеров
вызывают сдвиги. Всегда резервируй место! -->
<div style="min-height: 250px;">
<!-- Рекламный баннер загрузится сюда -->
</div>
3. Тяжёлый JavaScript блокирует INP
// ПЛОХО: долгая задача блокирует интерактивность
button.addEventListener('click', () => {
for (let i = 0; i < 10000000; i++) { /* тяжёлое вычисление */ }
updateUI;
});
// ХОРОШО: разбиваем на куски
button.addEventListener('click', async () => {
await new Promise(r => setTimeout(r, 0)); // Уступаем главный поток
const result = await computeInChunks(data);
updateUI(result);
});
Практика
- Установи
web-vitalsи выведи метрики в консоль на своём сайте - Проверь свой сайт в PageSpeed Insights — запиши все метрики
- Найди LCP-элемент на главной странице и оптимизируй его загрузку
- Добавь
width/heightко всем изображениям для улучшения CLS - Проверь Field Data в Google Search Console