Core Web Vitals у WordPress: реальні виправлення для LCP, INP і CLS

Було корисно?

Core Web Vitals не помиляються делікатно. Вони ламаються у день релізу, під час кампанії або одразу після того, як ви підписали «SLA з продуктивності», яку не обговорювали. І дивним чином завжди винен WordPress — поки ви не виміряєте стек і не виявите, що проблема насправді в темі, плагінах, сервері, CDN і 14 маркетингових тегах, які вам сказали, що «непідлягають обговоренню».

Якщо ви хочете, щоб LCP, INP і CLS поводилися, припиніть ганятись за випадковими порадами «як швидко зробити сайт». Почніть ставитися до сайту як до продакшн-системи: інструментуйте його, профілюйте, усувайте невідомі чинники та впроваджуйте зміни, які витримають реальний трафік.

Що LCP/INP/CLS означають у стеку WordPress

LCP: «Як швидко з’явилась головна річ?»

LCP (Largest Contentful Paint) зазвичай — це головне зображення, зображення запису або великий заголовок у верхній частині сторінки. Для WordPress LCP рідко буває «тільки мережею». Зазвичай це ланцюг причин:

  • Затримка відповіді сервера (TTFB): PHP, база даних, промахи кешу, повільне сховище, CPU steal, проблеми з апстрімом.
  • Ресурси, що блокують рендеринг: CSS, шрифти і іноді JS, які блокують відмалювання.
  • Рішення щодо медіа: неоптимізовані зображення, неправильні розміри, lazy-loading для LCP-зображення, відсутність preload.
  • Поведінка CDN/кешу: правила обходу, куки, фрагментація кешу, вибухи заголовка Vary.

Якщо у вас поганий LCP, найгірше виправлення — «встановити ще один плагін для продуктивності». Саме так ви отримуєте шість шарів кешу, які сперечаються про заголовки.

INP: «Як швидко сторінка відповіла людині?»

INP (Interaction to Next Paint) замінив FID як метрику «відчуття відповідності» сторінки. Це був не нудьгуючий хід Google; це визнання того, що одна перша взаємодія легко піддається обходу. INP карає довгі завдання у головному потоці, важкий JS і проблеми гідратації.

У WordPress більші проблеми з INP зазвичай походять від:

  • JS-бандлів, доданих плагінами (слайдери, конструктори сторінок, аналітика, чати).
  • Тематичних фреймворків, які привозять вантажівку JS для вирішення CSS-проблеми на велосипеді.
  • Занадто великого DOM, великої кількості обробників подій і сторонніх скриптів, що «допомагають» кожному кліку.
  • Реалій мобільних CPU: ваш лептоп не є базовим рівнем продуктивності; це привілей.

CLS: «Чи залишалась сторінка на місці?»

CLS (Cumulative Layout Shift) здебільшого самонавідуваний. Це відбувається, коли браузер починає малювати, а потім ви переставляєте меблі: зображення без розмірів, пізно підвантажувані шрифти, оголошення, що змінюють розміри, банери, які штовхають контент, повідомлення про куки, що з’являються нізвідки.

WordPress полегшує виникнення CLS, бо теми часто виводять «гнучку» розмітку, плагіни вставляють DOM після завантаження, а редактори люблять завантажувати зображення без узгоджених правил розмірів. Виправлення — не «відключити анімації». Виправлення — зарезервувати місце і контролювати пізні надходження.

Одна ідея, перефразована від Werner Vogels (Amazon), яка варто на екрані вашого монітора: Усе ламається; надійність приходить через інженерію для відмов, а не через припущення, що їх не буде.

Швидкий план діагностики (перший/другий/третій)

Це порядок, який швидко знаходить вузьке місце в production, не перетворюючи ваш тиждень на спекулятивний арт-проєкт.

Перший: визначте, чи проблема на сервері або на фронтенді

  • Перевірте TTFB і відсоток попадань у кеш. Якщо у вас відсутній кеш і PHP працює важко, ви ніколи не вирішите проблему «оптимізацією CSS».
  • Порівняйте холодний і теплий запит. Якщо теплий швидкий, а холодний повільний, у вас прогалини в кешуванні або дорогі uncached шляхи (куки, query string, варіанти для залогінених).

Другий: визначте елемент LCP і що його блокує

  • Чи є LCP-елементом зображення, блок або заголовок?
  • Чи затримується він через ресурси, що блокують рендеринг (CSS або шрифти)?
  • Чи ресурс LCP лениво підвантажується (не повинен)?

Третій: аудитуйте роботу головного потоку для INP

  • Шукайте довгі таски і великі JS-бандли.
  • Тимчасово відключіть сторонні скрипти, щоб виміряти їхній вплив.
  • Зменшіть DOM і уникайте важких віджетів конструкторів сторінок у верхній частині.

Потім: виправте CLS, зарезервувавши місце

  • Додайте width/height або CSS aspect-ratio для зображень та вставок.
  • Використовуйте font-display коректно і preload-те шрифти, які реально використовуються.
  • Припиніть інжектити банери, що штовхають контент після першого відмалювання.

Правило рішення: Якщо TTFB постійно високий — спочатку сервер/кеш. Якщо TTFB хороший, але LCP високий — виправляйте критичний шлях рендерингу й доставку LCP-елемента. Якщо INP високий — полюйте за довгими тасками і сторонніми скриптами. Якщо CLS високий — резервуйте місце і стабілізуйте шрифти/оголошення.

Цікаві факти й історичний контекст (чому все стало складнішим)

  • 2010-ті: Індустрія обожнювала «час завантаження сторінки» як одне число. Це було зручно і переважно марно.
  • Ера HTTP/2: Збирання всього в один файл перестало бути автоматично корисним; надмірне бандування може затримати перше відмалювання.
  • WordPress 5.5: Рідний lazy-loading для зображень з’явився за замовчуванням, що покращило багато сторінок — і водночас зламало LCP для сайтів, які лениво підвантажували герой-зображення без винятків.
  • Запуск Core Web Vitals: Google перейшов від виключно лабораторних метрик до акценту на field data (CrUX). Ваш «ідеальний Lighthouse» все ще може програти в реальних умовах користувачів.
  • FID → INP: FID міг виглядати добре, поки сторінка залишалася нестабільною після взаємодії. INP вимірює відгук по кількох взаємодіях, ускладнюючи приховування «JS-боргу».
  • Введення CLS: Частково це реакція на хаос макетів у рекламній індустрії — користувачі натискали не туди через стрибки контенту.
  • Вибух веб-шрифтів: Кастомні шрифти стали нормою, але також великим фактором для CLS/LCP, коли завантажуються пізно або погано заміняються.
  • Популяризація конструкторів сторінок: Вони прискорили публікацію контенту, але часто збільшили розмір DOM та додали зайвий JS/CSS, що позначається на INP і LCP.

Дві істини: продуктивність — це бізнес-фічa, а WordPress — найпоширеніший спосіб запускати баги продуктивності у великому масштабі.

LCP: реальні виправлення (не відчуття)

1) Зробіть TTFB нудним: попадання в кеш, передбачувані варіанти

LCP часто починається зі сервера. Якщо ваш HTML запізнюється, решта не має значення.

  • Кеш сторінок для анонімних користувачів: NGINX fastcgi_cache, Varnish, CDN HTML кеш або кеш у керованому хості.
  • Object cache для залогінених і динамічних шляхів: Redis або Memcached.
  • Розумний ключ кешу: уникайте фрагментації через куки, query string і варіанти по пристрою, якщо вони вам реально не потрібні.

2) Припиніть lazy-load для вашого LCP-зображення

LCP-елемент має завантажуватися рано, з високим пріоритетом. Якщо ваша тема додає loading="lazy" до герой-зображення, вона саботує метрику, яку ви намагаєтесь покращити.

Варіанти виправлення:

  • Виключте з логіки lazy-load зображення, що знаходяться у верхній частині сторінки.
  • Додайте fetchpriority="high" до LCP-зображення там, де це підтримується.
  • Preload-те точний варіант герой-зображення (уважно: preload-те саме те, що реально використовується).

3) Доставляйте правильне зображення, а не геркулесову помилку

Типова помилка WordPress: віддавати 2400px JPEG для мобільного вікна 390px під приводом «retina». Retina — це не дозвіл на надмір.

  • Правильно використовуйте srcset і sizes (WordPress робить це частково; теми можуть зламати).
  • Віддавайте перевагу AVIF/WebP, коли можливо.
  • Стискайте агресивно герой-зображення; користувачі більше запам’ятовують швидкість, ніж надтонкі текстури.

4) Позбавтесь render-blocking CSS правильним способом

«Вбудовувати критичний CSS» — це не релігія, а компроміс. Мета — швидко відмалювати контент у верхній частині сторінки, не змушуючи браузер чекати на великий файл стилів.

  • Мінімізуйте розмір CSS, видаліть невикористаний CSS.
  • Розділіть CSS так, щоб стилі для верхньої частини були доступні негайно.
  • Не привозьте п’ять фреймворків лише тому, що плагін хотів Bootstrap.

5) Шрифти: або завантажуйте їх свідомо, або не використовуйте

Завантаження шрифтів може впливати на LCP (пізнє відмалювання) і CLS (заміна). Якщо ви використовуєте кастомні шрифти:

  • Хостіть шрифти локально, щоб зменшити затримки сторонніх сервісів і покращити кешування.
  • Preload-те лише шрифти, що використовуються у верхній частині сторінки.
  • Використовуйте font-display: swap або optional залежно від вимог бренду і чутливості до CLS.

Жарт #1: «Легкова тема» — це як «легкий майонез»: вона існує, але все одно здебільшого — олія і жаль.

INP: реальні виправлення (ваш JS, ймовірно, бреше)

1) Видаліть JavaScript перед тим, як оптимізувати

INP безжальний до роботи головного потоку. Найчистіший виграш — видалення: менше скриптів, менше віджетів, менше обробників подій. Почніть зі сторонніх тегів і функцій конструктора сторінок.

2) Відкладіть некритичні скрипти, але не ламайте інтерактивність

«Відкласти весь JS» може обернутися проблемами, коли критичні скрипти потрібні для навігації, пошуку або меню. Суть у тому, щоб:

  • Завантажувати критично важливий для взаємодії JS раніше (малим).
  • Відкладати все інше.
  • Використовувати idle callbacks для неважливої роботи, де це доречно.

3) Зменшіть довгі таски: розбийте бандли, зменшіть роботу на подію

Якщо клік викликає 400ms задачу, користувач її відчуває навіть якщо сторінка «швидко завантажилась». Типові винуватці:

  • Велика маніпуляція DOM при кліку.
  • Важка аналітика, що виконується «після взаємодії».
  • Каруселі та бібліотеки анімацій, які перерендюють багато елементів.

4) Приручіть сторонні скрипти жорсткими межами

Сторонні скрипти — як підрядники: корисні, дорогі і час від часу лишають безладу. Дайте їм бюджет.

  • Завантажуйте їх лише на тих сторінках, де вони потрібні (чат не має бути на архіві блогу).
  • Відкладіть до прояву наміру користувача (наприклад, після скролу або кліку «відкрити чат»).
  • Проводьте регулярний аудит; маркетингові стеки накопичуються як нарости на корпусі корабля.

CLS: реальні виправлення (припиніть стрибки макета)

1) Завжди резервуйте місце для зображень, вставок та реклами

CLS найчастіше — це «відсутні розміри». WordPress може виводити width/height для зображень, але теми й конструктори іноді їх видаляють. Виправляйте це в джерелі.

  • Переконайтеся, що теги img містять атрибути width і height, або використовуйте CSS aspect-ratio.
  • Для вставок (YouTube, iframe) обгорніть у контейнер із aspect-ratio.
  • Для оголошень: визначте фіксовані слоти, а не «хай що випаде, те й буде».

2) Шрифти: зменшіть зсув через swap

Заміни шрифтів можуть змінювати метрики тексту. Стратегії:

  • Використовуйте fallback-шрифт з подібними метриками.
  • Розгляньте font-display: optional для вторинних шрифтів.
  • Preload-те основні шрифти, що використовуються у верхній частині сторінки.

3) Не інжектуйте банери, які штовхають контент після відмалювання

Повідомлення про куки, промо-бари, оверлеї «підписатись» — якщо вони штовхають контент вниз після першого відмалювання, ви явно створюєте CLS. Використовуйте оверлеї, що не впливають на рефлоу, або резервуйте місце з самого початку.

Жарт #2: CLS — це коли ваша сторінка перефарбовує меблі під час екскурсії. Ніхто не любить несподівані перестановки.

Практичні завдання з командами, виводами та рішеннями

Це перевірки, які я запускаю, перш ніж хтось почне «оптимізувати» щось. Кожне завдання містить команду, приклад виводу, що це означає, і рішення, яке на її основі приймається.

Завдання 1: Перевірити ефективність кешу з краю (HTML)

cr0x@server:~$ curl -sI https://example.com/ | egrep -i 'cache|age|x-cache|cf-cache-status|via|server|vary'
server: nginx
cache-control: public, max-age=60
age: 0
vary: Accept-Encoding, Cookie
x-cache: MISS

Що це означає: Ви варіюєте по Cookie, що ймовірно руйнує ключ кешу, і у вас промах у кеші.

Рішення: Переконайтеся, що анонімним користувачам не встановлюються зайві куки; звужуйте Vary; налаштуйте CDN/кеш сторінки, щоб ігнорувати неважливі куки.

Завдання 2: Виміряти TTFB і загальний час

cr0x@server:~$ curl -o /dev/null -s -w 'namelookup=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.com/
namelookup=0.004 connect=0.012 ttfb=0.680 total=1.102

Що це означає: Мережа в порядку; відповідь сервера повільна (TTFB ~680ms).

Рішення: Спріоритетизуйте серверне кешування, налаштування PHP-FPM і кеш об’єктів перед фронтендовими мікрооптимізаціями.

Завдання 3: Порівняти теплий кеш і холодний кеш (повторити запит)

cr0x@server:~$ for i in 1 2 3; do curl -o /dev/null -s -w "run=$i ttfb=%{time_starttransfer} total=%{time_total}\n" https://example.com/; done
run=1 ttfb=0.690 total=1.110
run=2 ttfb=0.180 total=0.410
run=3 ttfb=0.175 total=0.402

Що це означає: Холодний шлях дорогий; теплий — прийнятний. У вас є кеш, але він не потрапляється послідовно (або кеш замалий/відкидається).

Рішення: Збільшити покриття кешу, зменшити фрагментацію (куки/query string) та перевірити TTL/поведінку відкидання кешу.

Завдання 4: Швидко ідентифікувати кандидата LCP (приблизна евристика)

cr0x@server:~$ curl -s https://example.com/ | sed -n '1,220p' | egrep -n 'wp-post-image|hero|featured|sizes=|srcset=|fetchpriority|preload'
42:<img class="wp-post-image" src="https://example.com/wp-content/uploads/2025/hero.jpg" loading="lazy" decoding="async">

Що це означає: Можливе LCP-зображення явно лениве. Це може затримувати LCP.

Рішення: Виключіть герой/LCP-зображення із lazy-loading і розгляньте fetchpriority=high та коректний srcset.

Завдання 5: Підтвердити наявність розмірів зображень (попередження CLS)

cr0x@server:~$ curl -s https://example.com/ | grep -oE '<img[^>]+>' | head -n 3
<img src="https://example.com/wp-content/uploads/2025/hero.jpg" class="wp-post-image">
<img src="https://example.com/wp-content/uploads/2025/logo.png" class="custom-logo" width="180" height="48">
<img src="https://example.com/wp-content/uploads/2025/thumb.jpg" loading="lazy" width="768" height="512">

Що це означає: Перше зображення не має width/height. Класичний фактор CLS.

Рішення: Виправте вивід теми (додайте розміри) або застосуйте CSS aspect-ratio для відомих контейнерів.

Завдання 6: Перевірити насичення PHP-FPM і повільні запити

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running)
     Status: "Processes active: 48, idle: 2, Requests: 310, slow: 17, Traffic: 2.1req/sec"

Що це означає: Ви близькі до максимуму активних процесів; є повільні запити.

Рішення: Перевірте slowlog, збільшіть pm.max_children лише якщо дозволяють CPU/RAM, і зменшіть роботу PHP через кешування та очищення плагінів.

Завдання 7: Прочитати slowlog PHP-FPM, щоб знайти винуватців

cr0x@server:~$ sudo tail -n 25 /var/log/php8.2-fpm/www-slow.log
[27-Dec-2025 09:14:02]  [pool www] pid 21432
script_filename = /var/www/html/index.php
[0x00007f3a7c1a2a30] mysqli_query() /var/www/html/wp-includes/wp-db.php:2056
[0x00007f3a7c1a2910] query() /var/www/html/wp-includes/wp-db.php:1918
[0x00007f3a7c1a2800] get_results() /var/www/html/wp-includes/wp-db.php:3193
[0x00007f3a7c1a26e0] get_posts() /var/www/html/wp-includes/post.php:2543
[0x00007f3a7c1a25c0] Elementor\Plugin->init() /var/www/html/wp-content/plugins/elementor/includes/plugin.php:699

Що це означає: Повільний шлях включає важку ініціалізацію плагіна і запити до БД.

Рішення: Проведіть профілювання впливу плагінів, додайте object cache, зменшіть дорогі запити (або функції плагіна) і забезпечте кеш сторінки для анонімного трафіку.

Завдання 8: Перевірити MySQL/MariaDB на повільні запити

cr0x@server:~$ sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries'; SHOW VARIABLES LIKE 'slow_query_log';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries  | 128   |
+---------------+-------+
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | ON    |
+----------------+-------+

Що це означає: Є повільні запити і логування увімкнено.

Рішення: Перегляньте лог повільних запитів; відредагуйте індекси і запити плагінів перед тим, як масштабувати обладнання.

Завдання 9: Знайти топ повільних запитів (за часом)

cr0x@server:~$ sudo mysqldumpslow -s t -t 5 /var/log/mysql/mysql-slow.log
Count: 12  Time=1.24s (14s)  Lock=0.00s (0s)  Rows=1200.0 (14400), root[root]@localhost
  SELECT option_value FROM wp_options WHERE option_name = 'autoloaded_options'

Count: 9  Time=0.88s (7s)  Lock=0.01s (0s)  Rows=1.0 (9), root[root]@localhost
  SELECT * FROM wp_posts WHERE post_type='product' AND post_status='publish' ORDER BY post_date DESC LIMIT N

Що це означає: Автозавантажені опції і контентні запити повільні; автозавантаження опцій — класична причина уповільнення WP.

Рішення: Зменшіть кількість опцій з autoload (очистка плагінів), розгляньте persistent object caching, додайте/перевірте індекси для частих запитів.

Завдання 10: Перевірити стан Redis object cache

cr0x@server:~$ redis-cli info stats | egrep 'keyspace_hits|keyspace_misses|evicted_keys'
keyspace_hits:481230
keyspace_misses:220114
evicted_keys:9231

Що це означає: Промахів і відкидань достатньо. Можливо, кеш замалий або TTL налаштовано неправильно.

Рішення: Збільште maxmemory у Redis, налаштуйте політику відкидання і зменшіть фрагментацію кешу (групуйте ключі, уникайте кешування гігантських об’єктів).

Завдання 11: Підтвердити стиснення і типи контенту (контроль LCP payload)

cr0x@server:~$ curl -sI https://example.com/wp-content/themes/site/style.css | egrep -i 'content-encoding|content-type|cache-control'
content-type: text/css; charset=UTF-8
cache-control: public, max-age=31536000
content-encoding: br

Що це означає: Brotli увімкнено і TTL кешу довгий. Добре для повторних переглядів і зменшення об’єму передачі.

Рішення: Якщо кодування відсутнє — увімкніть gzip/br і перевірте налаштування CDN; якщо cache-control короткий — виправте заголовки кешування для статичних ресурсів.

Завдання 12: Виявити render-blocking CSS/JS з HTML (швидко й грубо)

cr0x@server:~$ curl -s https://example.com/ | egrep -n '<link[^>]+rel="stylesheet"|<script[^>]+src=' | head -n 12
18:<link rel="stylesheet" href="https://example.com/wp-content/plugins/elementor/assets/css/frontend.min.css">
19:<link rel="stylesheet" href="https://example.com/wp-content/themes/site/style.css">
61:<script src="https://example.com/wp-includes/js/jquery/jquery.min.js"></script>
62:<script src="https://example.com/wp-content/plugins/contact-form-7/includes/js/index.js"></script>

Що це означає: Декілька стилів і скриптів завантажуються рано. Деякі можуть бути непотрібні в верхній частині сторінки.

Рішення: Відкладіть некритичні скрипти, видаліть невикористані ресурси плагінів на сторінках, що їх не використовують, і розгляньте критичний CSS для верхньої частини.

Завдання 13: Знайти важкі ресурси за розміром

cr0x@server:~$ curl -s https://example.com/ | grep -oE 'https://example.com[^"]+\.(js|css)' | sort -u | while read -r u; do s=$(curl -sI "$u" | awk -F': ' 'tolower($1)=="content-length"{print $2}' | tr -d '\r'); printf "%10s %s\n" "${s:-0}" "$u"; done | sort -nr | head
    842112 https://example.com/wp-content/plugins/pagebuilder/assets/app.js
    238900 https://example.com/wp-content/themes/site/style.css
    121104 https://example.com/wp-content/plugins/slider/assets/slider.js

Що це означає: Плагін постачає 800KB JS-файл. Це майбутня проблема для INP на мобільних CPU.

Рішення: Видаліть або замініть плагін, завантажуйте його лише там, де треба, або розбийте і відкладіть. Не намагайтесь «мінімізувати» 800KB і думати, що цього достатньо.

Завдання 14: Перевірити таймінги upstream у NGINX, щоб розділити PHP і мережу

cr0x@server:~$ sudo awk '$9 ~ /200|301|302/ {print $NF}' /var/log/nginx/access.log | tail -n 5
rt=0.412 uct=0.000 uht=0.410 urt=0.410
rt=1.122 uct=0.001 uht=1.120 urt=1.120
rt=0.398 uct=0.000 uht=0.396 urt=0.396
rt=0.905 uct=0.000 uht=0.904 urt=0.904
rt=0.401 uct=0.000 uht=0.399 urt=0.399

Що це означає: Upstream header time (uht) відповідає request time (rt). Вузьке місце — PHP/додаток, не мережа клієнта.

Рішення: Зосередьтесь на часі виконання PHP, частоті попадань у кеш, запитах до БД і накладних витратах плагінів.

Типові помилки: симптом → корінь → виправлення

1) Симптом: LCP поганий на мобільних, але на десктопі все добре

Корінь: Занадто велике герой-зображення + забагато JS, що конкурує за пропускну здатність/CPU; мобільне уповільнення виставляє це назовні.

Виправлення: Віддавайте коректні за розміром адаптивні зображення, пріоритезуйте LCP-зображення (без lazy-load) і зменшіть JS/CSS у верхній частині.

2) Симптом: LCP сильно флуктуїрує між запусками

Корінь: Промахи кешу через куки/query string, змішані шари кешу або варіабельність оригіну (шумні сусіди, CPU steal).

Виправлення: Нормалізуйте ключі кешу, видаліть непотрібні куки, перевірте узгодженість CDN/оригінального кешу та стабілізуйте роботу оригіну (розмір FPM, здоров’я БД).

3) Симптом: INP погіршився після додавання аналітики/чату/A/B тестування

Корінь: Сторонні скрипти виконують довгі таски або додають дорогі обробники подій.

Виправлення: Відкладіть або умовно завантажуйте сторонні скрипти, видаліть дублі і встановіть бюджет для скриптів. Так, ви можете сказати маркетингу «ні».

4) Симптом: CLS стрибає на статтях із зображеннями

Корінь: Тема/конструктор прибирає width/height або використовує CSS, що викликає перефлоу зображень.

Виправлення: Переконайтеся, що присутні внутрішні розміри, використовуйте контейнери з aspect-ratio і уникайте пізньої обгортки зображень, яка змінює розміри.

5) Симптом: CLS стрибає у верхній частині сторінки

Корінь: Банер куків/промо-блок інжектується після першого відмалювання, штовхаючи контент вниз.

Виправлення: Резервуйте місце з початкового рендеру або використовуйте оверлеї, які не змінюють макет. Віддавайте перевагу server-side рендерингу заповнювачів для UI згоди.

6) Симптом: Сторінка здається чуйною в dev, але користувачі скаржаться на лаги

Корінь: Тестування на швидких пристроях і чистих мережах; реальні користувачі мають слабші CPU і фонові процеси.

Виправлення: Тестуйте з мобільним throttling, вимірюйте field data і оптимізуйте під слабкі пристрої (менше JS, менше DOM-вузлів, менше задач головного потоку).

7) Симптом: «Плагін оптимізації» покращує Lighthouse, але шкодить реальним користувачам

Корінь: Агресивне відкладення ламає критичні скрипти, викликає пізні зміни макета або створює race conditions і проблеми гідратації.

Виправлення: Вимкніть загальні оптимізації; впроваджуйте цілеспрямовані зміни: критичний CSS, селективне відкладання і завантаження ресурсів за сторінками.

Три корпоративні міні-історії з передової

Міні-історія 1: Інцидент через хибне припущення

Вони припустили, що «WordPress сторінки здебільшого статики». Сайт виглядав статичним: маркетингові сторінки, пости блогу, кілька шаблонів. Команда включила CDN і оголосила перемогу. Вони не перевірили куки. Вони не перевірили заголовки Vary. Вони не підтвердили, що оригінал реально віддає.

Потім запровадили плагін персоналізації. Він встановлював куку для кожного відвідувача, включно з анонімними, «на випадок, якщо вони згодом конвертуються». CDN шанобливо поважав Vary: Cookie, бо був коректним і відповідним стандартам. Рівень попадань у кеш впав. TTFB піднявся. LCP пішов у прірву.

Першою підказкою на чергуванні не був звіт Core Web Vitals. Це був графік CPU оригіну і черга PHP-FPM. Вчора все «було добре», але вчора ця кука не встановлювалася. Зміна не була зловмисною — просто непомірною і невиміряною.

Виправлення було буденним: прибрати куку для анонімних користувачів, нормалізувати правила кешування, щоб ігнорувати неважливі куки, і зафіксувати Vary, щоб один плагін не міг непомітно переписати стратегію кешування. Продуктивність повернулась. Команда також навчилась різниці між «працює в staging» і «працює за CDN з реальним трафіком».

Міні-історія 2: Оптимізація, що дала зворотний ефект

Інша організація мала проблему з INP і вирішила «вирішити JavaScript» за допомогою плагіна продуктивності, який відклав і затримав майже все. Це зробило Lighthouse щасливішим, що зробило лідерство щасливішим, і це змінилося на швидкий реліз. Ви вже здогадуєтесь, що стало далі.

На деяких шаблонах відкладений скрипт відповідав за меню навігації. На повільніших пристроях користувачі натискали на іконку «гамбургер» і нічого не відбувалось кілька митей. Інколи дві миті. Іноді меню відкрилось і одразу закрилось, бо обробники подій приєднувались пізно і спрацьовували в неправильному порядку. Підтримка називала це «зламаною навігацією». Аналітика показувала зростання bounce rate. Інженери — «весела п’ятниця».

Післяінцидентний огляд був болючим, бо ніхто не провів базовий тест взаємодії з профілем мобільного з обмеженими ресурсами. «Оптимізація» створила гонку між HTML paint, застосуванням CSS і відкладеною гідратацією JS. INP суттєво не покращився; довіра користувачів погіршилась.

Правильне виправлення виявилось меншим і більш хірургічним: тримати критичні для взаємодії скрипти раніше, видалити важку бібліотеку слайдера і відкласти сторонні теги до першого скролу або першої взаємодії. Продуктивність покращилася і, що важливіше, сайт перестав обманювати користувачів.

Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію

Одна команда, яку я поважаю, проводить щотижневу «перевірку активів». Це не гламурно. Це регулярна подія в календарі, де вони дифують кількість скриптів, сумарні байти JS, байти CSS і топ сторонніх доменів на ключових сторінках. Вони ставлять це як відстеження бюджету, а не як одноразовий аудит.

Під час великої кампанії нова версія контейнера tag manager випадково додала дублювання аналітичних бібліотек і інструмент теплових карт на кожну сторінку, включно з оформленням замовлення. Ніщо не впало. Але INP погіршився за кілька днів, і field data почала йти в неправильному напрямку.

Оскільки у них була ця нудна базова лінія, вони швидко виявили регресію. Вони відкотили версію контейнера і відновили правила роботи скриптів по сторінках. Без драми, без героїчних поступок, без північних розборок «чому кошик повільний».

Урок: ви не зможете управляти тим, чого не інвентаризуєте. Продуктивність — це не проєкт; це гігієна.

Чеклисти / покроковий план

Покроково: спочатку стабілізуйте LCP

  1. Виміряйте TTFB на ключових сторінках (головна, топова цільова сторінка, стаття, сторінка товару). Якщо він повільний — виправляйте origin/кеш перед роботою з CSS.
  2. Підтвердьте поведінку попадань у кеш (CDN і origin). Усуньте фрагментацію кешу, спричинену куками.
  3. Ідентифікуйте елемент LCP (зазвичай герой-зображення/блок заголовка). Переконайтесь, що він не ленивий і має коректні адаптивні розміри.
  4. Зменшіть ресурси, що блокують рендеринг: видаліть невикористаний CSS, вбудуйте критичний CSS якщо це виправдано, і мінімізуйте кількість шрифтів.
  5. Перевірте в умовах, наближених до поля: мобільне обмеження ресурсів і холодний кеш.

Покроково: виправте INP без ламання сайту

  1. Перелічіть усі сторонні скрипти і вирішіть, на яких сторінках вони потрібні. «Всі сторінки» — рідко правда.
  2. Видаліть дублюючі плагіни і функції. Замініть важкі віджети на прості альтернативи.
  3. Відкладіть некритичний JS, але залиште критичні для взаємодії скрипти раніше.
  4. Зменшіть складність DOM у верхній частині: конструктори сторінок можуть створювати в 10 разів більше розмітки для того самого вигляду.
  5. Повторно протестуйте взаємодії (відкриття меню, додати в кошик, валідація форм) на середніх Android-профілях.

Покроково: ліквідуйте регресії CLS назавжди

  1. Забезпечте розміри для зображень і вставок у шаблонах теми.
  2. Стабілізуйте шрифти: preload-те необхідне, уникайте пізніх замін, підбирайте адекватні fallback-и.
  3. Контролюйте банери: резервуйте місце або використовуйте оверлеї, що не рефлоять контент.
  4. Аудитуйте рекламу та спонсорські слоти: визначайте фіксовані контейнери і уникайте зміни розмірів після завантаження.
  5. Додайте перевірки регресій: кожен новий плагін/зміна теми має проходити перевірку CLS на ключових шаблонах.

FAQ

1) Що спочатку виправляти: LCP, INP чи CLS?

Виправляйте те, що погано в field data, але почніть з того, що явно керується інфраструктурою й кешуванням, якщо воно явно зламане. Високий TTFB тягне LCP і марнує час, якщо ви спочатку працюєте з CSS.

2) Чи може CDN «вирішити» Core Web Vitals для WordPress?

CDN може сильно покращити TTFB і статичні активи, але він не виправить render-blocking CSS, роботу головного потоку JS або зсуви макета. Це необхідна інфраструктура, але не заміна стратегії продуктивності.

3) Чи завжди корисний lazy-loading?

Ні. Lazy-load використовуйте для зображень нижче фолдa. Не ленивіть LCP-елемент. Також будьте обережні з lazy-loading iframe поблизу верху — вони все одно можуть спричинити зсув, якщо не зарезервували місце.

4) Чи допомагають плагіни продуктивності?

Іноді. Вони також створюють непрозору поведінку і «одно-клікові» зміни, які важко проаналізувати. Використовуйте їх лише якщо можете виміряти, що саме вони змінюють: заголовки, HTML-вивід, атрибути скриптів і поведінку кешу.

5) Чому Lighthouse виглядає добре, а Search Console каже «потребує покращення»?

Lighthouse — це лабораторні дані. Search Console (через CrUX) відображає реальних користувачів. Реальні користувачі мають повільніші пристрої, гірші мережі і більше варіативності. Оптимізуйте для field performance, а не для трофейних скриншотів.

6) Чи допомагає оновлення PHP для Core Web Vitals?

Може покращити TTFB шляхом скорочення часу серверного виконання, що впливає на LCP. Воно не вирішить INP, викликаний важким клієнтським JS, і не зупинить CLS. Проте тримайте PHP актуальним; старі рантайми повільніші і менш безпечні.

7) Який найшвидший спосіб покращити CLS у WordPress?

Виправте розміри зображень. Переконайтеся, що кожне зображення у верхній частині має width/height або контейнер із aspect-ratio. Потім працюйте з банерами і шрифтами.

8) Як поводитись зі сторонніми скриптами, не починаючи політичної війни?

Дайте їм бюджет і дашборд: «Цей тег коштує X ms INP на мобільних». Запропонуйте умовне завантаження по сторінках і відкладене виконання як компроміс. Дані роблять розмову менш емоційною.

9) Чи потрібен Redis object cache, якщо в мене вже є page cache?

Якщо більшість трафіку анонімна і обслуговується з page cache/CDN, object cache менш критичний. Якщо у вас є залогінені користувачі, WooCommerce або динамічні сторінки, object caching може суттєво зменшити TTFB.

10) Чи виправить усе зміна теми?

Перехід від важкої теми конструктора до легшої може швидко покращити всі три метрики. Але якщо справжня проблема — фрагментація кешу, повільні запити до БД або сторонні скрипти, нова тема вас не врятує.

Наступні кроки, які можна відправити цього тижня

  1. Запустіть швидкий план діагностики і вирішіть: сервер-перший чи фронтенд-перший. Не робіть обох одночасно, якщо вам не до вподоби неоднозначні результати.
  2. Виправте фрагментацію кешу: усуньте непотрібні куки для анонімних користувачів; нормалізуйте поведінку Vary; перевірте попадання в кеш CDN і origin.
  3. Зробіть LCP-елемент свідомим: без lazy-load для героя, коректний srcset/sizes і пріоритет доставки.
  4. Обріжте JS радикально: видаліть один важкий плагін/віджет перед тим, як «оптимізувати» бандли. Видалення краще за хитрі рішення.
  5. Зарезервуйте простір макета: додайте розміри/aspect-ratio усьому, що у верхній частині; стабілізуйте банери і шрифти.
  6. Додайте gate для регресій: щотижнева перевірка активів + проста перевірка «додали скрипти/байти/DOM?» перед релізами.

Core Web Vitals — не загадка. Вони — дзеркало. Якщо ваш WordPress сайт повільний або стрибає, метрики скажуть правду — різко, постійно і перед вашими клієнтами.

← Попередня
Продуктивність Ceph на Proxmox повільна: 10 перевірок, які справді знаходять вузьке місце
Наступна →
Зниження напруги GPU: тихий трюк продуктивності, про який не кажуть

Залишити коментар