Skip to main content
Назад до блогу
4 хв читання

Коли Lighthouse CI впав на 20 балів — 8 годин на пошук

Оцінка продуктивності впала з 96 до 76 за ніч. Ні змін коду, ні нових залежностей. Причина: комбінація затримки Google Fonts з edge-сервера та зображення, що не було lazy-loaded.

performancenext.js

Понеділок ранок. Lighthouse CI фейлиться на стейджинг-деплої. Оцінка продуктивності: 76. Минулого тижня: 96. Ніхто не пушив код на вихідних. Немає оновлень залежностей. Немає змін конфігу.

Я витратив 8 годин на пошук причини. Ось шлях зневадження.

Година 1: Очевидні перевірки

Перша думка: нестабільний тест. Lighthouse-оцінки варіюються на ±3–5 балів через мережеві умови та навантаження CPU. Падіння на 20 — не варіативність, а регресія.

Локальний запуск Lighthouse: 94. Достатньо близько до базового. Не регресія в коді.

Lighthouse на задеплоєному стейджинг-URL: 76. Збігається з CI.

Розрив між локальним і задеплоєним сказав мені: проблема в інфраструктурі, не в коді.

Година 2: Аналіз водоспаду

Chrome DevTools → вкладка Performance на стейджинг-URL. Водоспад показав:

  1. HTML: 180мс (нормально)
  2. Основний JS-бандл: 120мс (нормально)
  3. Файл шрифту: 2,100мс (ненормально — зазвичай 80мс)
  4. Hero-зображення: 350мс (нормально)

Файл шрифту вантажився з іншого CDN, ніж зазвичай. Google Fonts через fonts.googleapis.com. Нічого не змінювалось. Але час відповіді — змінився.

curl URL шрифту з Vercel edge: 2.3 секунди. З локальної машини: 45мс.

Година 3: Шрифтовий гак

Google Fonts був повільним з Vercel edge. Чому? CI-ранер був в іншому регіоні, і edge-функція робила крос-регіональний запит до Google Fonts. Заголовки відповіді: cache-control: private, max-age=86400. private означає, що CDN не може кешувати. Тільки браузер. На свіжому запуску Lighthouse (порожній кеш) кожен запит шрифту йде на origin.

Фікс: Селф-хостинг шрифтів. Завантажити WOFF2-файли, покласти в /public/fonts/, посилатися через @font-face в CSS.

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-var.woff2') format('woff2');
  font-display: swap;
  font-weight: 100 900;
}

Після деплою з селф-хостингом: завантаження шрифту з 2,100мс до 40мс. Lighthouse: 88. Краще — але все ще не 96.

Година 5: Зображення, що не було lazy

Бракує 8 балів. Запустив Lighthouse з Treemap. LCP-елемент — hero-зображення, коректно. Але час LCP — 2.8с, було 1.2с.

Перевірив hero <Image>:

<Image src="/hero-bg.webp" alt="..." fill priority sizes="100vw" />

priority — коректно для hero. Тоді чому LCP повільний?

Вкладка Network. Hero-зображення вантажиться нормально. Але друге велике зображення нижче згину теж завантажувалось з priority:

// Секція About — нижче згину
<Image src="/about-photo.webp" alt="..." width={600} height={800} priority />

Хтось додав priority до фото секції About при оновленні контенту. Браузер попередньо завантажував два великих зображення одночасно. Hero-зображення конкурувало за bandwidth з about-фото, збільшуючи LCP на ~1.5 секунди.

Фікс: Прибрати priority зі зображення нижче згину.

Після деплою: LCP знизився до 1.3с. Lighthouse: 95.

Година 7: Чому CI зловив, а локально — ні

Локальний Lighthouse працює на повній пропускній здатності з низькою затримкою. Проблеми шрифту та зображення були приховані швидким локальним з'єднанням. CI-ранер симулює троттлінг мобільного з'єднання (4G), де конкуренція за bandwidth між двома priority-зображеннями та повільним шрифтом реально мала значення.

Саме тому ти запускаєш Lighthouse у CI, а не тільки локально.

Година 8: Запобігання в майбутньому

Три ґарди:

  1. Lighthouse CI budget: фейлить перевірку, якщо продуктивність падає нижче 90 або LCP перевищує 2.5с.
  2. Правило для priority на зображеннях: тільки одне зображення на сторінку має мати priority.
  3. Селф-хостинг шрифтів як правило проєкту: жодних посилань на Google Fonts.

Таймлайн

ЧасДіяОцінка
Помітив фейл CI76
Визначив затримку Google Fonts з edge76
Селф-хостинг шрифтів88
Прибрав зайвий priority зі зображення нижче згину95
Додав CI-бюджети + правила запобігання95 (захищено)

Падіння на 20 балів. Дві кореневі причини, обидві невидимі локально. 8 годин на пошук, 10 хвилин на фікс. Ось так працює зневадження продуктивності.


Бачиш регресії продуктивності, які не можеш пояснити? Напиши — я тримаю Lighthouse 98 на продакшн-сайтах і можу проаудити твій пайплайн продуктивності.