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 на продакшн-сайтах и могу проаудировать твой пайплайн производительности.