Оптимізація Core Web Vitals
Core Web Vitals — три метрики Google, які напрямки впливають на ранжування з 2021 року. Погані показники дають штраф "Page Experience"; хороші — дають перевагу при рівних інших факторах.
Три метрики та цільові значення
| Метрика | Добре | Потребує вдосконалення | Погано |
|---|---|---|---|
| LCP (Largest Contentful Paint) | ≤ 2,5 с | 2,5–4,0 с | > 4,0 с |
| INP (Interaction to Next Paint) | ≤ 200 мс | 200–500 мс | > 500 мс |
| CLS (Cumulative Layout Shift) | ≤ 0,1 | 0,1–0,25 | > 0,25 |
INP замінив FID у березні 2024. FID вимірював тільки першу взаємодію; INP — усі взаємодії протягом сеансу.
LCP (Largest Contentful Paint) — швидкість завантаження головного елемента
LCP — момент, коли найбільший елемент (звичайно hero-зображення або H1) з'являється на екрані.
Головні причини поганого LCP:
- Hero-зображення не preload
- Повільний TTFB сервера
- Render-blocking CSS/JS
- Зображення в WebP/AVIF не оптимізовано
Ключові оптимізації:
<!-- Preload LCP-зображення -->
<link rel="preload" as="image" href="/images/hero.webp"
imagesrcset="/images/hero-400.webp 400w, /images/hero-800.webp 800w, /images/hero-1200.webp 1200w"
imagesizes="100vw">
<!-- fetchpriority для тега <img> -->
<img src="/images/hero.webp" fetchpriority="high" loading="eager"
width="1200" height="630" alt="...">
# Прискорення TTFB через кеш на Nginx
location ~* \.(html)$ {
proxy_cache_valid 200 5m;
add_header X-Cache-Status $upstream_cache_status;
}
INP (Interaction to Next Paint) — відзивчивість інтерфейсу
INP вимірює затримку між дією користувача (клік, натискання клавіші) та наступним рендерингом.
Причини поганого INP:
- Довгі JavaScript-задачі (> 50ms) блокують main thread
- Синхронні обчислення в обробниках подій
- Занадто часті setState у React без батчингу
Оптимізації:
// Розбивка довгих задач через scheduler
async function processLargeList(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Yield main thread кожні 50 елементів
if (i % 50 === 0) {
await new Promise(r => setTimeout(r, 0));
}
}
}
// React 18: автоматичний батчинг уже ввімкнений
// Для явного контролю — startTransition для некритичних оновлень
import { startTransition } from 'react';
function handleSearch(query) {
// Терміне оновлення (поле введення)
setInputValue(query);
// Некритичне (список результатів) — можна відкласти
startTransition(() => {
setSearchResults(filterResults(query));
});
}
CLS (Cumulative Layout Shift) — стабільність макету
CLS — сума смішень елементів при завантаженні сторінки.
Типові причини:
- Зображення без
width/height(браузер не резервує місце) - Шрифти викликають FOUT/FOIT
- Динамічно вставлені баннери/реклама
- Анімації, що змінюють розміри елементів
Оптимізації:
<!-- Завжди вказуйте розміри зображень -->
<img src="photo.webp" width="800" height="600" alt="...">
<!-- Для адаптивних — aspect-ratio у CSS -->
<style>
.hero-image {
aspect-ratio: 16 / 9;
width: 100%;
}
</style>
/* Резервуйте місце для шрифтів */
@font-face {
font-family: 'Inter';
font-display: optional; /* або swap + size-adjust */
src: url('/fonts/inter.woff2') format('woff2');
}
/* Для font-display: swap — компенсуйте розмірну різницю */
@font-face {
font-family: 'InterFallback';
src: local('Arial');
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
size-adjust: 107%;
}
Інструменти вимірювання
Лабораторні дані (синтетичні):
- PageSpeed Insights — швидка перевірка конкретної сторінки
- Lighthouse (DevTools) — детальний аудит
- WebPageTest — розширений аналіз з waterfall
Польові дані (реальні користувачі):
- CrUX (Chrome User Experience Report) — у Search Console
- web-vitals npm-пакет для збору в аналітику
// Відправка Web Vitals у GA4
import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals';
function sendToAnalytics({ name, value, rating, id }) {
gtag('event', name, {
event_category: 'Web Vitals',
event_label: id,
value: Math.round(name === 'CLS' ? value * 1000 : value),
non_interaction: true,
custom_map: { metric_rating: rating }
});
}
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);
Пріоритети
- LCP — зазвичай дає найбільший ефект: preload hero-зображення, FastCGI/Redis кеш для TTFB
- CLS — швидко виправляється додаванням розмірів зображенням та налаштуванням шрифтів
- INP — складніше: потребує профілювання конкретних взаємодій через Performance DevTools
Час оптимізації: 1–2 тижні для комплексної роботи за всіма трьома метриками.







