Аудит сайта через PageSpeed, Lighthouse и Core Web Vitals: пошаговый разбор
Основной чат
Чат для вайбкодеров: новости, гайды, поиск исполнителей, маркетплейс и разбор реальных кейсов.
Три инструмента и их роли
Прежде чем бежать что-то проверять — разберёмся что за инструменты существуют и чем они отличаются.
PageSpeed Insights (PSI)
Ссылка: pagespeed.web.dev
Это онлайн-инструмент от Google. Анализирует одну страницу и даёт оценку от 0 до 100 для мобайла и десктопа отдельно.
Что важно понять: PSI показывает два типа данных.
Лабораторные данные (Lab data) — Lighthouse запускается на серверах Google в контролируемых условиях. Это синтетический тест: фиксированное железо, фиксированная сеть, один конкретный момент времени.
Полевые данные (Field data / CrUX) — реальные данные от реальных пользователей Chrome за последние 28 дней. Это Chrome User Experience Report (CrUX). Если сайт мало посещают — полевых данных может не быть.
Разница принципиальная: лабораторные данные нужны чтобы диагностировать проблемы. Полевые данные нужны чтобы понять как сайт ощущается реальными пользователями.
Lighthouse
Где запустить: Chrome DevTools → вкладка Lighthouse (F12 → Lighthouse)
Тот же движок что используется в PSI, но запускается в вашем браузере. Анализирует не только производительность — ещё доступность, SEO, best practices.
Преимущество перед PSI: можно тестировать локальные сборки, staging-окружения, страницы за авторизацией. PSI не может добраться до закрытых страниц.
Core Web Vitals
Это не инструмент — это три конкретные метрики которые Google считает ключевыми для пользовательского опыта:
- LCP (Largest Contentful Paint) — когда загрузился главный контент
- INP (Interaction to Next Paint) — насколько быстро реагирует интерфейс
- CLS (Cumulative Layout Shift) — насколько стабильна верстка при загрузке
Эти три метрики есть и в PSI, и в Lighthouse, и в Google Search Console.
Как читать отчёт PageSpeed Insights
Открываешь pagespeed.web.dev, вставляешь URL, жмёшь «Анализ». Через 20–30 секунд — отчёт. Разбираем его сверху вниз.
Первый экран: оценки и полевые данные
Вверху — два числа: оценка для мобайла и для десктопа. Мобайл почти всегда ниже — потому что тестируется на эмулированном медленном устройстве (Moto G4) с медленным соединением (4G).
Цветовая кодировка:
- 90–100 🟢 — хорошо
- 50–89 🟡 — требует улучшений
- 0–49 🔴 — плохо
Ниже — полевые данные (Field Data) если они есть. Это реальные пользователи. Здесь та же цветовая кодировка для каждой из трёх Core Web Vitals метрик.
Важно: оценка — это агрегированное число. Две страницы могут иметь оценку 65 по совершенно разным причинам. Смотри не на оценку — смотри на конкретные метрики.
Метрики производительности
Под полевыми данными — раздел «Диагностика производительности» с шестью метриками:
FCP (First Contentful Paint) — когда появился первый элемент контента (текст или изображение). Норма: < 1.8 секунды.
LCP (Largest Contentful Paint) — когда загрузился самый крупный элемент на странице (обычно hero-изображение или заголовок). Норма: < 2.5 секунды. Это одна из Core Web Vitals.
TBT (Total Blocking Time) — суммарное время блокировки основного потока JavaScript. Лабораторный прокси для INP. Норма: < 200 мс.
CLS (Cumulative Layout Shift) — насколько элементы «прыгают» при загрузке. Норма: < 0.1. Это Core Web Vitals.
Speed Index — насколько быстро визуально заполняется экран. Норма: < 3.4 секунды.
INP (Interaction to Next Paint) — время от действия пользователя до следующего отрисованного кадра. Это ключевая метрика интерактивности в 2024+. Норма: < 200 мс. Core Web Vitals.
Раздел «Возможности» (Opportunities)
Это конкретные действия которые улучшат LCP и другие метрики — с оценкой потенциальной экономии в секундах.
Здесь приоритизируй по потенциальному выигрышу. «Удалить неиспользуемый JavaScript» с экономией 2.3 секунды — важнее чем «Использовать формат WebP» с экономией 0.1 секунды.
Раздел «Диагностика» (Diagnostics)
Более детальные рекомендации — не напрямую влияющие на оценку, но влияющие на качество.
Core Web Vitals: разбор каждой метрики
LCP (Largest Contentful Paint)
Что это: момент когда загрузился самый крупный видимый элемент страницы. Обычно это:
- Hero-изображение
- Большой блок текста (заголовок на текстовой странице)
- Видео-постер
Нормы:
- ✅ < 2.5 секунды — хорошо
- 🟡 2.5–4 секунды — требует улучшений
- 🔴 > 4 секунды — плохо
Как узнать что является LCP-элементом:
В Chrome DevTools → Performance → запусти запись → перезагрузи страницу → в разделе Timings найди LCP-маркер → кликни → увидишь какой элемент.
Или в Lighthouse-отчёте — в деталях LCP написано что именно.
Почему LCP медленный — типичные причины:
Медленный сервер (TTFB) — браузер долго ждёт первый байт от сервера. Всё остальное бессмысленно оптимизировать если TTFB > 600 мс. Решение: CDN, кэширование на сервере, апгрейд хостинга.
LCP-изображение не preload'ится — браузер обнаруживает изображение только когда парсит CSS или рендерит HTML. Если это hero-картинка — она должна грузиться с самого начала. Решение:
<link rel="preload" as="image" href="hero.webp">в<head>.Изображение не оптимизировано — PNG 2 МБ вместо WebP 200 КБ. Решение: конвертация в WebP/AVIF, правильные размеры (не грузить изображение 3000px шириной если отображается 800px).
Render-blocking ресурсы — CSS и JS в
<head>без defer/async блокируют рендеринг. Решение: критичный CSS — inline в<head>, некритичный — сmedia="print"и JS-переключением, JavaScript — сdeferилиasync.Медленные шрифты — браузер ждёт загрузки шрифта прежде чем показать текст. Решение:
font-display: swap+ preload критичных шрифтов.
INP (Interaction to Next Paint)
Что это: время от любого взаимодействия пользователя (клик, тап, нажатие клавиши) до момента когда браузер отрисовал следующий кадр в ответ. Заменил FID (First Input Delay) как метрику интерактивности в 2024 году.
Нормы:
- ✅ < 200 мс — хорошо
- 🟡 200–500 мс — требует улучшений
- 🔴 > 500 мс — плохо
Почему INP медленный:
INP страдает когда основной поток (main thread) занят. Причины:
- Тяжёлые JavaScript-задачи блокирующие поток
- Много обработчиков событий
- Сложные перерасчёты стилей (layout thrashing)
- Синхронные операции в обработчике клика
Как диагностировать:
Chrome DevTools → Performance → запиши 5–10 секунд взаимодействия → найди в треке «Main» длинные жёлтые/красные задачи (Long Tasks) — это то что блокирует поток.
В LoAF (Long Animation Frames) — новый раздел в Chrome 123+ — видны конкретные анимации и скрипты которые создают задержку.
Как чинить:
- Разбивать длинные задачи через
setTimeout(0)илиscheduler.yield() - Использовать Web Workers для тяжёлых вычислений
- Debounce/throttle для частых событий (scroll, resize, input)
- Виртуализация длинных списков (react-virtual, tanstack-virtual)
CLS (Cumulative Layout Shift)
Что это: суммарная «нестабильность» верстки при загрузке. Когда элементы «прыгают» — пользователь случайно нажимает не то, теряет место в тексте, испытывает раздражение.
Нормы:
- ✅ < 0.1 — хорошо
- 🟡 0.1–0.25 — требует улучшений
- 🔴 > 0.25 — плохо
Как считается: каждый unexpected layout shift имеет impact fraction (% экрана который сдвинулся) × distance fraction (как далеко сдвинулся). CLS — сумма всех таких событий за сессию.
Типичные причины CLS:
1. Изображения без размеров
<!-- ❌ Плохо: браузер не знает сколько места зарезервировать -->
<img src="hero.jpg" alt="Hero">
<!-- ✅ Хорошо: резервирует место заранее -->
<img src="hero.jpg" alt="Hero" width="1200" height="600">
Или через CSS: aspect-ratio: 16/9.
2. Реклама и embed-контент без зарезервированного места
Рекламный блок появляется после загрузки страницы и сдвигает контент. Решение: резервируй место через min-height для рекламного блока.
3. Динамически вставляемый контент
Баннер «принять cookies» появляется поверх контента и сдвигает его. Решение: фиксированное позиционирование (position: fixed) вместо смещения потока.
4. Шрифты вызывающие FOUT/FOIT
Текст сначала показывается системным шрифтом, потом заменяется кастомным — и слегка сдвигается (разные размеры букв). Решение: font-display: optional (не показывает кастомный шрифт если не загружен) или size-adjust, ascent-override для максимального совпадения с fallback-шрифтом.
Как диагностировать:
Chrome DevTools → Performance → включи «Web Vitals» в настройках → запись при перезагрузке → в треке «Experience» видны CLS-события с указанием элементов.
Или: в Lighthouse-отчёте в деталях CLS — список конкретных элементов которые сдвигались.
Полный алгоритм аудита: шаг за шагом
Шаг 1: Полевые данные из Search Console
Начни не с Lighthouse, а с Google Search Console → Core Web Vitals.
Там видишь реальные данные по всем страницам сайта с разбивкой «хорошо / требует улучшений / плохо». Это позволяет приоритизировать: какие страницы и какие метрики проблемные у реальных пользователей.
URL: search.google.com/search-console → Core Web Vitals (в левом меню)
Шаг 2: Лабораторный анализ проблемных страниц
Для каждой проблемной страницы из Search Console — запусти PSI. Смотри на:
- Что является LCP-элементом
- TBT (прокси для INP)
- CLS-нарушители
- Топ-5 «Opportunities» по потенциальной экономии
Шаг 3: Глубокий анализ в DevTools
Для сложных случаев — Chrome DevTools → Performance.
F12 → Performance → ⚙️ настройки:
- CPU throttling: 4x slowdown (эмуляция среднего смартфона)
- Network: Fast 4G
→ нажми Record → перезагрузи страницу → через 5–7 секунд Stop
Что смотреть в трейсе:
- Main thread: длинные красные задачи (Long Tasks > 50 мс) — это TBT/INP
- Network: waterfall загрузки ресурсов — что грузится последовательно вместо параллельно
- Timings: маркеры FCP, LCP, DCL (DOMContentLoaded)
- Frames: где происходят перерасчёты стилей (фиолетовые блоки)
Шаг 4: Анализ сети (Network panel)
DevTools → Network → перезагрузи страницу → сортируй по Size.
Ищи:
- Изображения > 500 КБ (кандидаты на оптимизацию)
- JavaScript-бандлы > 300 КБ (кандидаты на code splitting)
- CSS-файлы > 100 КБ (возможно много неиспользуемого)
- Ресурсы без кэша (нет Cache-Control заголовков)
- Ресурсы с другого домена которые блокируют рендеринг
Шаг 5: Coverage — неиспользуемый код
DevTools → Ctrl+Shift+P → «Show Coverage» → Record → перезагрузи.
Покажет процент неиспользуемого JavaScript и CSS. 50–70% неиспользуемого JavaScript на первой загрузке — это норма для сложных SPA. Но > 80% — значит что-то явно не так с code splitting.
Приоритизация: что чинить первым
Не всё одинаково важно. Вот порядок по влиянию:
1. TTFB (Time to First Byte) — серверное время ответа
Если TTFB > 600 мс — всё остальное бессмысленно оптимизировать. Браузер ждёт сервер прежде чем начать что-то делать.
Как проверить: в Network → первый запрос → вкладка Timing → «Waiting (TTFB)».
Как улучшить:
- CDN (Content Delivery Network) — ответ приходит с ближайшего сервера
- Серверный кэш — не пересчитывать страницу для каждого запроса
- Оптимизация базы данных (медленные запросы)
- Апгрейд хостинга
2. LCP-изображение — самое влияющее на восприятие
- Формат WebP или AVIF (в среднем 30–50% меньше PNG при том же качестве)
fetchpriority="high"на LCP-изображении- Правильный
srcsetчтобы не грузить 2000px на телефон - Preload:
<link rel="preload" as="image" fetchpriority="high" href="hero.webp">
3. Render-blocking ресурсы
CSS в <head> без media атрибута блокирует рендеринг. JavaScript в <head> без defer блокирует рендеринг.
<!-- ❌ Блокирует рендеринг -->
<script src="analytics.js"></script>
<!-- ✅ Загружается параллельно, выполняется после HTML -->
<script src="analytics.js" defer></script>
<!-- ✅ Загружается и выполняется параллельно (порядок не гарантирован) -->
<script src="widget.js" async></script>
4. JavaScript bundle size
Крупные бандлы — главная причина высокого TBT и медленного INP.
- Code splitting: загружай только то что нужно для текущей страницы
- Tree shaking: удаляй неиспользуемый код из библиотек
- Lazy loading: компоненты ниже fold грузи отложено
5. Изображения ниже fold
Все изображения которые не видны при первой загрузке:
<img src="photo.jpg" alt="..." loading="lazy">
Атрибут loading="lazy" — браузер не загружает изображение пока оно не приближается к viewport. Для изображений в первом экране — не используй (задержит LCP).
Типичные сценарии и решения
Сценарий: высокий CLS на мобайле из-за баннера
Баннер cookies появляется поверх контента и сдвигает его.
/* ❌ Плохо: баннер в потоке документа */
.cookie-banner {
position: relative;
}
/* ✅ Хорошо: фиксированный, не сдвигает поток */
.cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
}
Сценарий: медленный LCP из-за hero-изображения
Hero-изображение 1.2 МБ в PNG, грузится после CSS.
Чеклист исправления:
- Конвертируй в WebP:
cwebp -q 80 hero.png -o hero.webp - Добавь
srcsetдля разных размеров - Добавь preload в
<head>:
<link rel="preload" as="image" href="hero.webp"
imagesrcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
imagesizes="100vw"
fetchpriority="high">
- На img добавь
fetchpriority="high"
Сценарий: высокий TBT из-за тяжёлого JavaScript
TBT 1800 мс. В Coverage видно что 60% бандла не используется на текущей странице.
Чеклист:
- Анализ через Webpack Bundle Analyzer или Rollup Visualizer — что занимает место
- Dynamic imports для компонентов которые не нужны сразу
- Проверить нет ли дублирующихся зависимостей
- Заменить тяжёлые библиотеки на лёгкие альтернативы (moment.js → date-fns, lodash → lodash-es с tree shaking)
Инструменты для мониторинга в реальном времени
Разовый аудит — хорошо. Регулярный мониторинг — лучше.
Google Search Console — бесплатно, реальные данные от пользователей Chrome, оповещения при ухудшении. Обязательный инструмент для каждого сайта.
web-vitals.js — библиотека от Google для сбора CWV в аналитику:
import {onLCP, onINP, onCLS} from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);
Подключи к своей аналитике (GA4, Amplitude, самописная) — получай реальные данные от своих пользователей.
Lighthouse CI — запускай Lighthouse автоматически в CI/CD при каждом деплое. Если оценка упала ниже порога — сборка падает.
Vercel Speed Insights, Netlify Analytics — встроенные инструменты у популярных хостингов.
WebPageTest (webpagetest.org) — более детальный чем PSI, позволяет тестировать с разных локаций, разных устройств, с видео-записью загрузки.
Часто задаваемые вопросы
«Оценка 100 = сайт быстрый?»
Нет. Оценка 100 в Lighthouse означает что ты хорошо выступил на синтетическом тесте. Реальные пользователи на реальных устройствах с реальным интернетом — другая история. Смотри на полевые данные в CrUX.
«Моя оценка каждый раз разная — почему?»
Лабораторные тесты имеют вариативность ±10–15% из-за загрузки серверов, шума в процессоре, параллельных задач. Для точности: запускай несколько раз и смотри на среднее. Или используй WebPageTest с несколькими прогонами.
«Сайт быстрый на десктопе, но медленный на мобайле в PSI»
Lighthouse для мобайла тестирует на эмулированном Moto G4 (медленный CPU) с эмулированным 4G соединением. Это намеренно пессимистичные условия. Реальный опыт зависит от твоей аудитории — если большинство на флагманах с 5G, оценка 55 для мобайла не означает плохой опыт.
«Реклама роняет CWV — что делать?»
Резервируй место под рекламный блок даже до загрузки рекламы: min-height: 250px (стандартный баннер). Используй position: sticky или fixed для блоков которые появляются поверх контента.
ИИ и аудит производительности: как Claude помогает
Промпт: интерпретировать отчёт PSI
Вот данные из PageSpeed Insights для нашего сайта:
Мобайл: оценка [число]
LCP: [значение] сек
INP/TBT: [значение] мс
CLS: [значение]
FCP: [значение] сек
Топ-5 рекомендаций из раздела Opportunities:
[список с временем экономии]
Проанализируй:
1. Какие метрики критичны (влияют на Core Web Vitals и ранжирование)?
2. Что чинить в первую очередь — по соотношению влияния и сложности?
3. Что из списка Opportunities может быть решено быстро (1–2 дня)?
4. Какие проблемы требуют глубокой технической работы?
Промпт: план оптимизации для разработчика
Нам нужно улучшить следующие показатели сайта:
— LCP: [текущее] → цель [целевое]
— CLS: [текущее] → цель < 0.1
— TBT: [текущее] → цель < 200 мс
Стек: [React/Vue/Next.js/WordPress/другое]
Хостинг: [описание]
Основные проблемы из Lighthouse: [список]
Составь технический план оптимизации:
1. Quick wins (до 1 дня работы) — что даст быстрый результат
2. Medium (1–3 дня) — более сложные изменения
3. Long-term (неделя+) — архитектурные улучшения
Для каждого пункта: что именно делать (конкретные изменения в коде или конфигурации).
Промпт: объяснить результаты стейкхолдерам
Нам нужно объяснить результаты аудита производительности руководству / клиенту.
Текущая ситуация:
— Оценка PSI мобайл: [число]
— Основные проблемы: [список]
— Время загрузки: [секунды]
Напиши объяснение для нетехнической аудитории:
1. Что означают эти показатели простыми словами
2. Как это влияет на пользователей (конкретно)
3. Как это влияет на бизнес (конверсия, SEO, удержание)
4. Что мы планируем исправить и какого результата ожидаем
Без технического жаргона. Максимум 1 страница.
Промпт: code review для производительности
Проверь этот код на проблемы с производительностью (LCP, CLS, INP):
[вставь HTML/CSS/JavaScript]
Контекст: это [описание страницы/компонента].
Найди:
1. Что может вызывать медленный LCP
2. Что может вызывать CLS
3. Что может блокировать main thread (влияет на INP)
4. Неоптимальная загрузка ресурсов
Для каждой проблемы: конкретное исправление с кодом.
Чеклист аудита производительности
Инструменты:
- Проверены Core Web Vitals в Google Search Console (реальные данные)
- Запущен PSI для главной и ключевых посадочных страниц (мобайл!)
- Запущен Lighthouse в DevTools для страниц за авторизацией
- Проверен TTFB в Network panel
LCP:
- Определён LCP-элемент (что именно)
- Изображение в WebP/AVIF с правильными размерами
- Preload для LCP-изображения в
<head> -
fetchpriority="high"на LCP-изображении - TTFB < 600 мс
CLS:
- Все изображения имеют атрибуты width и height
- Место под рекламу и embed зарезервировано
- Динамически появляющийся контент не сдвигает поток (position: fixed)
- Шрифты с
font-display: swapи fallback близкий по размеру
INP / TBT:
- Нет Long Tasks > 50 мс в main thread (DevTools Performance)
- JavaScript-бандлы < 300 КБ для первой загрузки
- Сторонние скрипты загружаются с
deferилиasync - Тяжёлые обработчики с debounce/throttle
Ресурсы:
- Изображения ниже fold с
loading="lazy" - Критичный CSS inline или preload
- Некритичный JavaScript с
defer - Cache-Control заголовки на статических ресурсах
- Gzip или Brotli сжатие включено на сервере