Core Web Vitals для PHP-сайтів: як виправити LCP, INP та CLS
Core Web Vitals вимірюються у браузері, але на PHP-сайті значна частина результату визначається сервером. У цьому гайді - куди дивитися в першу чергу, які зміни в PHP, nginx і фронтенд рухають цифри і як вимірювати, не обманюючи себе.
Коротко
- Три метрики: Largest Contentful Paint ( LCP) менше 2,5 с, Interaction to Next Paint ( INP) менше 200 мс, Cumulative Layout Shift ( CLS) менше 0,1; оцінюється 75 перцентиль реальних користувачів.
- Почніть із часу відповіді сервера ( TTFB): OPcache, налаштований пул PHP-FPM, кеш сторінок чи фрагментів і CDN зазвичай дають найбільший виграш по LCP на PHP-сайтах.
- Займіться LCP-елементом усвідомлено: підберіть розмір hero-картинки, віддавайте WebP, додайте
fetchpriority="high"і ніколи не ліниве завантаження. - Резервуйте місце під зображення, рекламу і блоки, що вбудовуються, щоб прибрати зсуви макета; використовуйте
font-display: swapта передзавантаження шрифтів. - Спочатку дивіться польові дані ( Search Console, CrUX), потім відтворюйте проблему в Lighthouse та панелі Performance браузера.
Core Web Vitals для PHP-сайтів – це не лише тема фронтенду. Повільна PHP-сторінка може витрачати секунду просто на генерацію HTML і ніяка оптимізація картинок цього не поверне. І навпаки: швидкий сервер не допоможе, якщо найбільше малювання блокує hero-картинка на 1,5 МБ. Так ми підходимо до обох сторін на своїх PHP-сайтах (integrono.com працює на PHP-FPM за nginx та Cloudflare) та у проектах клієнтів.
Що вимірюють Core Web Vitals
- LCP ( Largest Contentful Paint): коли змальований найбільший видимий елемент (зазвичай hero-картинка або блок заголовка). Добре – 2,5 секунди і менше.
- INP ( Interaction to Next Paint): як швидко сторінка візуально реагує на кліки, торкання та натискання клавіш за все відвідування. Добре – 200 мс і менше.
- CLS ( Cumulative Layout Shift): наскільки контент «стрибає» при завантаженні. Добре – 0,1 і менше.
Google оцінює їх за польовими даними реальних користувачів Chrome, по 75 перцентилю, окремо для мобільних і десктопу. Тому один повільний шаблон або одна повільна країна може провалити всю групу. Лабораторні інструменти типу Lighthouse необхідні для налагодження, а не для підсумкової оцінки.
Крок 1. Вимірюйте правильно
- Відкрийте звіт Core Web Vitals у Google Search Console, щоб побачити, які групи URL не проходять і за якою метрикою.
- Перевірте в PageSpeed Insights по одному URL із кожної проблемної групи. Важливим є верхній блок «польові дані», а блок Lighthouse нижче - лабораторний тест, який пояснює причини.
- Використовуйте панель Performance у Chrome DevTools із уповільненням CPU у 4 рази та мережею «Slow 4G», щоб відтворити типовий мобільний досвід.
- Для постійного моніторингу збирайте дані реальних користувачів бібліотекою
web-vitalsта надсилайте їх до аналітики.
<script type="module">
import {onLCP, onINP, onCLS} from 'https://unpkg.com/web-vitals@4?module';
const send = (m) => navigator.sendBeacon('/vitals', JSON.stringify({
name: m.name, value: m.value, id: m.id, url: location.pathname
}));
onLCP(send); onINP(send); onCLS(send);
</script>
Крок 2. Спочатку виправте час відповіді сервера ( TTFB)
У LCP входить час до першого байта. Якщо HTML генерується 800 мс, третина бюджету вже витрачено. На PHP-сайтах основні важелі такі:
- Увімкніть OPcache та переконайтеся, що його розміру вистачає для всіх скриптів. Без нього PHP компілює заново файли при кожному запиті.
- Налаштуйте PHP-FPM. Занадто мало воркерів ставить запити у чергу, надто багато вичерпує пам'ять. Слідкуйте на сторінці статусу PHP-FPM за «listen queue» та «max children reached».
- Кешуйте сторінки цілком для анонімних відвідувачів (nginx
fastcgi_cache, кеш відповідей у Laravel або правила кешування Cloudflare), а фрагменти та результати запитів - у Redis. - Виправте повільні запити. Увімкніть slow query log, знайдіть патерни N+1 та додайте індекси. Сторінка з 120 запитами повільна за будь-якої версії PHP.
- Оновлення PHP. Нові версії швидше та економніше по пам'яті.
# php.ini (production)
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0 ; reload php-fpm on each deploy
# php-fpm pool
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pm.max_requests = 500
Значення pm.max_children вважайте реальною пам'яті: розділіть пам'ять, яку можна віддати PHP, на середній розмір процесу воркера (дивіться через ps). При validate_timestamps=0 не забувайте перезавантажувати PHP-FPM після кожного деплою, інакше залишиться в пам'яті старий код.
На рівні веб-сервера увімкніть HTTP/2 або HTTP/3, Brotli або gzip та довгі заголовки кешування для статики:
location ~* \.(?:css|js|webp|avif|jpg|png|svg|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
Використовуйте версійні імена файлів або параметр ?v= на основі часу зміни файлу, щоб immutable ніколи не віддавав застарілі ресурси.
Крок 3. Виправте LCP-елемент
Знайдіть LCP-елемент у PageSpeed Insights або панелі Performance у DevTools. На більшості контентних сторінок це hero-картинка. Далі:
- Не використовуйте для неї ліниве завантаження.
loading="lazy"на LCP-картинці затримує її. Натомість поставтеfetchpriority="high". - Віддавайте необхідний розмір. Картинка 2400 px для слота 900 px – зайві байти. Використовуйте
srcsetтаsizes. - Використовуйте WebP або AVIF. Звичайна економія - від 30 до 60 відсотків у порівнянні з JPEG при подібній якості.
- Уникайте ланцюжків. Картинка, задана тлом у CSS або вставлена JavaScript, з'являється пізно. Покладіть її в HTML як
<img>. - Використовуйте preconnect або свій хостинг для інших джерел, від яких залежить LCP (шрифти, CDN картинок).
<img src="/images/hero-1200.webp"
srcset="/images/hero-640.webp 640w, /images/hero-1200.webp 1200w"
sizes="(max-width: 1040px) 92vw, 960px"
width="1200" height="630"
alt="Descriptive alt text"
decoding="async" fetchpriority="high">
За таким шаблоном зроблено обкладинки статей у цьому блозі: два розміри WebP, явні розміри та високий пріоритет завантаження для hero.
Крок 4. Заберіть зсуви макету ( CLS)
- Завжди задавайте
widthіheight(абоaspect-ratioу CSS) для зображень, відео та iframe, щоб браузер резервував місце. - Резервуйте місце під банери, сповіщення про cookie та рекламу. Вставляйте їх у контейнер із фіксованою мінімальною висотою, а не зсувайте контент після завантаження.
- Шрифти: використовуйте
font-display: swapабоoptional, завантажуйте основний файл шрифту і робіть subset. Підберіть запасний шрифт зі схожими метриками. - Не вставляйте контент над показаним, якщо це не результат дії користувача.
- Анімуйте через
transformіopacity, а чи не через властивості, що змінюють макет (top,height).
Крок 5. Поліпшіть INP: менше JavaScript в основному потоці
INP - найновіша метрика, і PHP-розробники її часто упускають, тому що сервер на неї безпосередньо не впливає. Причини лежать у браузері: довгі завдання великих бандлів, важкі сторонні скрипти (аналітика, чат-віджети, менеджери тегів) і обробники, які синхронно роблять занадто багато роботи.
- Проведіть аудит сторонніх сценаріїв. Видаліть ті, що нікому не потрібні, інші завантажуйте з
deferабо після першої взаємодії. - Розбивайте довгі завдання. Діліть роботу на частини через
requestIdleCallback,setTimeoutабо Scheduler API, важкі обчислення виносите у Web Worker. - Тримайте DOM невеликим. Тисячі вузлів уповільнюють кожне оновлення.
- Уникайте примусових синхронних перерахунків макета у циклах (чергування читання та запису властивостей макета).
- Показуйте миттєвий зворотний зв'язок (стан натискання або індикатор) до початку повільної роботи.
Крок 6. Закріпіть результат у процесі деплою
Продуктивність деградує непомітно: новий тег, важча обкладинка, зайвий запит на головну. Додайте Lighthouse CI або регулярну перевірку через PageSpeed API для п'яти найважливіших шаблонів, задайте бюджети ( LCP, загальний розмір JS, вага картинок) і налаштуйте сповіщення про перевищення. Порівнюйте TTFB до та після кожного релізу: якщо він підскочив, причина майже завжди у запиті чи кеші, який перестав спрацьовувати.
Реалістичний порядок робіт
- Виміряйте польові дані та визначте проблемні групи URL.
- Увімкніть OPcache, перегляньте налаштування PHP-FPM, додайте кеш цілих сторінок для анонімного трафіку.
- Виправте hero-картинки: формат, розмір, пріоритет, розміри.
- Зарезервуйте місце для всього, що завантажується пізно.
- Скоротіть та відкладіть JavaScript, приберіть непотрібні сторонні скрипти.
- Виміряйте повторно через 28 днів: польові дані - ковзне вікно.
Поліпшення з'являтимуться в Search Console поступово: звіт використовує приблизно останні 28 днів, тому виправлення, викачуване сьогодні, повністю виявиться приблизно через місяць.
Чим ми можемо допомогти
Ми займаємося продуктивністю PHP і Laravel проектів в рамках технічного SEO та окремими роботами: кеш, запити, зображення та правки фронтенду прямо в коді. Якщо хочете зрозуміти, які зміни вище окупляться саме на вашому сайті, запишіться на консультацію або аналіз сервера. Більш широкий чек-лист зі сканування та індексації – у статті технічний SEO-аудит.
Часті запитання
Які значення Core Web Vitals вважаються добрими?
LCP 2,5 секунд і менше, INP 200 мілісекунд і менше і CLS 0,1 і менше, за 75-м перцентилем реальних відвідувань.
Чи впливають Core Web Vitals на позиції Google?
Вони входять у сигнали page experience та є фактором ранжування помірної ваги. Релевантність та контент важливіші, але повільна чи нестабільна сторінка гірше конвертує, і для бізнесу це часто дорожче.
Як PHP впливає на Core Web Vitals ?
В основному через час відповіді сервера ( TTFB), яке входить до LCP. Його знижують OPcache, налаштований PHP-FPM, кешування, швидкі запити та актуальна версія PHP. На INP та CLS PHP безпосередньо не впливає, вони залежать від фронтенд-коду та верстки.
Чому PageSpeed Insights показує не ті цифри, що Search Console ?
PageSpeed Insights показує лабораторний тест одного URL плюс польові дані, якщо вони є, а Search Console - польові дані за групами URL приблизно за 28 днів. Про успіх судіть за польовими даними.
Через скільки поліпшення з'являться у Search Console ?
Звіт Core Web Vitals використовує ковзне вікно в 28 днів реальних даних, тому повний ефект виправлення видно приблизно через чотири тижні.
Безкоштовний discovery-дзвінок
Хаотичний стек чи зависла інтеграція - Integrono намітить найрозумніший перший крок.
Ви отримуєте senior-погляд на бюджетні пастки, залежності і коли купувати, склеювати чи писати - до старту оплати. CEO лишається в контурі.