Прямой ответ
Core Web Vitals — три метрики пользовательского опыта (Google-стандарт, но ценность не в SEO, а в том, что они измеряют реальные ощущения): LCP (Largest Contentful Paint — когда показался самый крупный элемент — цель ≤2.5 с на p75 полевых пользователей), INP (Interaction to Next Paint — отклик на взаимодействие — клик/тап до следующего кадра — цель ≤200 мс; заменил FID в 2024 — измеряет всю задержку, не только первую), CLS (Cumulative Layout Shift — суммарная «прыгучесть» вёрстки — цель ≤0.1 — «кнопка уехала из-под пальца» — главная боль мобильного веба). Ключевое различие: лабораторные данные (Lighthouse/PageSpeed на эталонном железе — повторяемы, для разработки) против полевых/RUM (реальные пользователи на реальных сетях — CrUX/свой RUM-сбор — именно p75 полевых — критерий); оптимизировать надо полевые (лабораторный «100/100» при полевом LCP 4 с — бывает: тест на быстром интернете не видит медленных пользователей — HTTP/3-аудитория — плохие сети живут в полях). Приоритеты LCP-оптимизации (порядок важен — начинать сверху): (1) время до первого байта — TTFB (бэкенд/хостинг/кеш — заголовки кеша + CDN — медленный сервер никакой фронтенд не спасёт); (2) загрузка критичного ресурса (hero-изображение — preload+fetchpriority=high, не lazy-load выше сгиба — «ленивая загрузка главного баннера» — антипаттерн, встречающийся постоянно); (3) рендер-блокирующие ресурсы (CSS в head синхронный — критичный CSS инлайном, остальное async; JS — defer/модули — парсинг не блокировать); (4) клиентский рендер (CSR-страницы — HTML пуст до JS — LCP поздно — SSR/SSG для контент-страниц — SEO+витрины — статическая генерация решает). CLS-дисциплина: размеры у всего (width/height или aspect-ratio у img/iframe/видео — место зарезервировано до загрузки), шрифты без скачков (font-display: swap + preload основных + size-adjust для fallback — «текст прыгнул при подмене шрифта» — классика), вставки контента не поверх существующего (баннеры/куки-плашки — место в потоке, не overlay на готовое). INP — самый «бэкенд-независимый»: долгий JS на главном потоке — причина №1 (задачи >50 мс дробить — scheduler.yield/requestIdleCallback — тяжёлые вычисления в Web Worker), сторонние скрипты (аналитика/виджеты — CSP-учёт стороннего — INP часто деградирует подключённым маркетингом, не кодом команды).
Измерение: инструменты и процесс
Набор: PageSpeed Insights (полевые CrUX-данные по URL/домену + лабораторный Lighthouse — одна страница, обе перспективы — стартовая точка любого аудита), Lighthouse в DevTools/CI (лабораторные прогоны на каждый PR — бюджет производительности: «LCP-лаб не хуже X» — CI-интеграция — Lighthouse CI хранит историю — регрессии ловятся до прода), CrUX Dashboard (полевые метрики домена из Chrome-данных — 28-дневные окна — для публичных сайтов с трафиком), свой RUM (web-vitals JS-библиотека — LCP/INP/CLS с каждого визита — отправка в свою аналитику (Sentry Performance принимает из коробки / ClickHouse-агрегация (событийная аналитика) — 30 строк подключения — бесценные данные «какие страницы/устройства/регионы страдают»); DevTools-разбор: Performance-панель (трейс загрузки — водопад ресурсов/долгие задачи), Coverage (неиспользуемый CSS/JS — «бандл 2 МБ, использовано 180 КБ» — код-сплиттинг по данным, не по догадке), Network-приоритеты (critical-цепочка видна — preload/приоритеты правятся здесь); процесс: аудит (PSI+RUM по топ-20 страницам) → худшие по p75 → причины из трейсов → фиксы по приоритетам → замер в полях через 2–4 недели (CrUX-окна — мгновенной обратной связи нет — RUM даёт быстрее); бюджеты в Definition of Done новых страниц («LCP лаб < 2 с, CLS < 0.05, бандл <+50 КБ» — ревью-чек-лист — производительность как функциональность, не «потом докрутим»).
Оптимизации: бэкенд, доставка, фронтенд
Бэкенд/TTFB (первый байт — фундамент LCP): кеш страниц/фрагментов (публичные страницы — CDN/edge-кеш (CDN) с s-maxage (заголовки) — TTFB с секунд до десятков мс; приватные — фрагментный кеш в приложении (кеш-паттерны) + оптимизация запросов (N+1/индексы (SQL) — «страница 800 мс в сервере» — трейсинг покажет где (трейсы)); стриминг HTML (первый байт рано, тело потоком — SSR-фреймворки умеют — TTFB-иллюзия скорости реальна); 103 Early Hints (preload-заголовки до HTML — CDN-поддержка растущая — h2/h3-контекст). Доставка: сжатие (brotli/gzip — текст ×3–5 меньше — nginx brotli-модуль), HTTP/2+3 (мультиплексирование/мобильные — протоколы), CDN для статики (edge ближе к пользователю — RTT сокращается географически — CDN-практика), preload критичного (hero-image/основной шрифт — <link rel=preload> — загрузка начинается с HTML-парсингом, не с открытием тега), preconnect к обязательным origin'ам (DNS+TLS до запроса — сторонние шрифты/аналитика — 100–300 мс экономии). Изображения (LCP-элемент часто картинка — полный разбор): AVIF/WebP + srcset под вьюпорты (десктоп-герой 2 МБ на мобильном — классика потерь), lazy ниже сгиба / eager+fetchpriority выше, размеры-атрибуты всегда. JS/рендер (INP+LCP): код-сплиттинг по маршрутам (первая страница тащит бандл всего приложения — роут-разделение — сборка), tree-shaking зависимостей (moment→dayjs-класс — Coverage-панель покажет мёртвый вес), defer/async атрибуты, тяжёлое — Web Workers, стороннее — после интерактивности (facade-паттерн: виджет чата грузится по клику, не сразу — «живой чат» стоит 400 мс INP всему сайту — фасад возвращает); шрифты: preload основного, font-display: swap (текст виден сразу fallback'ом), size-adjust метрики подгоняют (CLS от подмены — шрифтовые скачки — минимум), subset кириллица/латиница раздельно (полный шрифт 300 КБ против 80 КБ subset).
Практический сценарий: карточка товара с LCP 5.2 с → 1.9 с
Исходник: e-commerce, карточка товара — главная по трафику; CrUX: LCP p75 — 5.2 с (плохо), CLS 0.21 (очень плохо), INP 340 мс (плохо) — весь набор красный. Аудит (PSI + Performance-трейс + свой RUM по устройствам): TTFB 900 мс (серверный рендер с 14 запросами к БД — трейс (Jaeger) — N+1 по отзывам+рекомендациям), hero-фото 1.8 МБ JPEG на всех устройствах (без srcset, lazy-load (!) на первом экране), CSS 340 КБ одним файлом (используется 41 КБ — Coverage), 6 сторонних скриптов до интерактивности (аналитика×2, чат, пиксель, видео-плеер 800 КБ), шрифт без preload со сменой метрик (CLS-вклад), изображения без размеров (прыжки при загрузке). Фиксы по приоритетам (3 недели): (1) TTFB: N+1 закрыт joinedload+кеш рекомендаций в Redis (кеш) — 900→240 мс; CDN на страницу с s-maxage=30 для анонимов (логин-трафик мимо кеша — заголовки) — p75 TTFB 60 мс; (2) hero: AVIF/WebP srcset (1.8 МБ → 90–280 КБ по устройствам — изображения), eager+fetchpriority=high+preload, width/height — CLS от героя ушёл; (3) CSS: критический инлайн (12 КБ), остальное — роут-сплит async (340→48 КБ на первую загрузку); (4) сторонние: чат/видео — facade по клику, аналитика — после load с задержкой (INP-вклад −180 мс); (5) шрифт: preload+swap+size-adjust, размеры у всех img/iframe (остаточный CLS — плашка куки перенесена в поток). Замеры: лаб LCP 5.2→1.4 с; полевые через 4 недели: LCP p75 1.9 с (зелёный), CLS 0.04 (зелёный), INP 190 мс (зелёный); RUM по сегментам: мобильный LTE LCP 2.4 с (было 6.8 — CDN+AVIF+srcnet — h3 включён заодно — доля h3 38%); бизнес-эффект: конверсия карточки +0.6 п.п. за месяц (A/B не проводили — до/после с сезонной поправкой — тест-дисциплина — строго говоря, слабее доказательства, но направление несомненно); бюджет в Definition of Done закреплён (Lighthouse-CI в PR — регресс LCP>15% — блокирующий комментарий). Урок в runbook: «аудит витрины — раз в квартал, RUM — всегда» — следующий квартальный аудит нашёл деградацию от нового виджета за дни, не месяцы.
FAQ
Стоит ли гнаться за 100/100 в Lighthouse? Нет как за самоцелью: лабораторный скор — инструмент разработки (регрессии/сравнения), критерий — полевые p75 (реальные пользователи/сети/устройства); «100 в лабе» достижим урезанием функциональности, бесполезной пользователю; здравая цель: полевые метрики в зелёной зоне + лаб-бюджеты против регрессий; перфекционизм за зелёной зоной (LCP 1.2 → 0.9) — отдача падает резко — усилия в функциональность, не в последние миллисекунды.
CLS-«прыжки» только от картинок бывают? Нет — источники: изображения/видео без размеров (классика), dynamically injected контент (баннеры/плашки вставляют поверх/выше — сдвигают всё ниже — вставлять с резервом места или overlay), веб-шрифты (подмена fallback→web меняет метрики — size-adjust/swap-стратегии), анимации без transform (анимация top/left перекладывает поток — transform/opacity — композиторные, без layout), iframe-вставки без размеров; диагностика — Performance-панель «Layout Shift» события с виновниками (элементы и сдвиги буквально названы) — CLS-отладка из «магии» стала точной инженерией.
Что важнее для b2b-дашборда: LCP или INP? Обычно INP: дашборд — интерактивный инструмент (клики/фильтры/сортировки — отклик решает опыт; LCP «первой отрисовки» важен один раз за сессию, INP — сотни раз); приоритеты: долгий JS дробить/воркеры, тяжёлые перерисовки таблиц — виртуализация (рендер видимого — тысячи строк в DOM — смерть INP — react-window-подходы), дебаунс фильтров, оптимистичный UI (отклик мгновенный, данные догоняют — WebSocket/SSE для живых обновлений); LCP-работа — базовая (скелетоны/сплиттинг), но «вылизывать LCP дашборда до 1 с» при INP 500 мс — неправильный приоритет.
Как быстро проверить свой сайт прямо сейчас? Маршрут пяти минут: PageSpeed Insights по главной+топ-странице (полевые данные сразу — если трафик есть), DevTools → Performance → запись перезагрузки (водопад/долгие задачи — причины видны), Lighthouse-прогон (лаб-скор+рекомендации), Coverage-панель (мёртвый вес CSS/JS), Network с throttling «Slow 4G» (реальная картина мобильной загрузки — «на моём макбуке летает» — не данные о пользователях); результат — список из 5–10 конкретных причин (обычно: TTFB, hero-картинка, блокирующий CSS, сторонние скрипты, шрифты) — дальше по приоритетам из статьи; регулярность — RUM-подключение (30 строк) превращает разовый аудит в постоянную видимость.
Источники: web.dev (Core Web Vitals, optimize LCP), документация Lighthouse — ссылки в шапке.