Метрики Core Web Vitals давно перестали быть внутренней кухней инженеров: поисковые системы прямо используют их в ранжировании, и медленный сайт теряет позиции ещё до всяких споров о качестве контента. Три показателя - задержка главного содержимого, отклик на взаимодействие, стабильность вёрстки - описывают пользовательский опыт понятными словами, на которых сходятся и браузеры, и менеджеры, и инженеры. Оптимизация этих цифр при этом не искусство: у каждой метрики известная механика, у каждой механики проверенный набор приёмов, и ниже все они разобраны в рабочем порядке от измерения до удержания результата.

Отправная точка любой оптимизации производительности - честное измерение на живом трафике. Лабораторные прогоны показывают картину в контролируемых условиях, полевые данные - жизнь на реальных устройствах, и решения принимаются по вторым, потому что медленная половина аудитории живёт не в лаборатории, а в метро и на стареньких телефонах. Целевой ориентир для всех трёх метрик - попадание в зелёную зону у семидесяти пяти процентов визитов, и именно перцентиль, а не среднее, является честной единицей отчёта. Три метрики при этом не соревнуются между собой: страница обязана проходить по всем, потому что опыт пользователя целостен, и рекордная скорость загрузки не компенсирует прыгающие кнопки. Отчёт по трём зонам на одной странице читается за минуту и управляет приоритетами квартала.

Задержка главного содержимого лечится приоритетами и весом

Метрика LCP измеряет время от начала навигации до появления крупнейшего элемента экрана - героя, баннера, главного смыслового блока. Часы этой метрики тикают с самого начала навигации, и типичные виновники известны годами: медленный ответ сервера, блокирующие ресурсы, тяжёлое изображение героя, шрифты, прячущие текст. Лечение начинается с критического пути отрисовки: главный контент получает приоритеты сети и рендера, всё остальное переводится в отложенный режим:

<link rel="preload" as="image" href="/hero.avif" fetchpriority="high">
<script defer src="/app.js"></script>
<img src="/hero.avif" width="1200" height="600" fetchpriority="high" decoding="async" alt="Пример работы">

Изображение героя - самый частый тормоз этой метрики: оригинальные файлы в мегабайтах, загрузка без приоритета, отсутствие размеров. Современные форматы сжимают картинку в разы, атрибуты ширины и высоты резервируют место, высокий приоритет ставит героя в начало очереди сети. Серверная часть добавляет свой вклад: время до первого байта - фундамент метрики, и кэш ответов вместе с доставкой из ближайшей точки убирает сотни миллисекунд до того, как браузер начнёт что-либо рисовать. Кэш разметки при этом работает наравне с кэшем статики: страницы, собранные заранее или отдающие каркас мгновенно, стартуют с меньшего времени, и тяжёлая персонализация уезжает на второй экран, где её ждут, а не блокируют первый.

Шрифты при этом либо помогают, либо саботируют: предзагруженный файл с показом запасного шрифта до загрузки основного не прячет текст и не роняет строки. Лениво подключённый шрифт, который подменяет текст после первой отрисовки, добавляет свою долю в задержку и в скачки вёрстки одновременно - двойной счёт по двум метрикам разом:

без оптимизации: ответ 600мс + картинка 1200мс = LCP ~1.8с
с оптимизацией: ответ 220мс + preload героя = LCP ~0.9с

Отложенные ниже первого экрана блоки при этом не считаются гостями метрики: всё, что человек увидит после прокрутки, обязано грузиться лениво, и честная граница между первым экраном и остальным - первый шаг оптимизации, который не требует ни одной строки сложного кода.

Картинки ниже первого экрана при этом не просто откладываются, но и получают подходящие размеры по правилам адаптивных вариантов: телефон скачивает четырёхсотый файл, монитор - полуторатысячный, и экономия на каждом визите складывается в терабайты на масштабе проекта. Разница размеров составляет основную экономию мобильной половины трафика.

Отклик на действия лечится дисциплиной главного потока

Вторая метрика - INP - измеряет время от действия человека до визуального ответа интерфейса: клик, тап, нажатие клавиши. Браузер исполняет обработчики интерфейса в одном потоке, и длинные задачи процессора - скелет в шкафу отзывчивости: пока поток занят пересчётом списка, нажатия ждут. Порог здорового отклика измеряется двумя сотнями миллисекунд на большинстве взаимодействий, и современные страницы превышают его чаще всего тремя путями: гигантские бандлы скриптов, сторонние виджеты и тяжёлые обработчики на каждое движение:

button.addEventListener("click", async () => {
  const { buildReport } = await import("./report.js");
  const data = await collect();
  show(buildReport(data));
});

Разбиение длинных задач - основной приём: вычисления делятся на короткие порции с возвратом управления между ними, и интерфейс отвечает между порциями. Динамический импорт привозит тяжёлый код в момент необходимости, а не при загрузке страницы. Сторонние скрипты проходят аудит как внутренние: каждый виджет объясняет свою цену и ценность, и не подтвердившие себя покидают страницу.

Порядок загрузки при этом планируется как порядок сцены: интерактивные элементы первого экрана оживают первыми, аналитика и тяжёлые редакторы - после. Приоритет загрузки - это дизайн, выполненный в сетевом стеке, и он решает больше, чем любой отдельный хак отрисовки.

Ввод при этом обрабатывается с приоритетом: обработчики событий не тянут за собой пересчёты, отрисовка изменений приостанавливает менее важную работу, и касание кнопки ощущается мгновенным даже на среднем телефоне. Оптимизация отклика - это и есть настоящая работа над ощущением, что сайт летает, потому что человек судит о скорости не по тестам, а по тому, отвечает ли страница на его действия.

События при этом делятся по цене: ввод текста и нажатия обрабатываются немедленно, пересчёты зависимых данных - отложенно, и реакция на каждое движение курсора - главный кандидат на задержку. Инструменты записывают медленные обработчики по именам, и правка обычно умещается в перенос вычисления на один кадр позже.

Стабильность вёрстки лечится зарезервированным местом

Третья метрика - CLS - измеряет неожиданные визуальные сдвиги вёрстки: кнопка уезжает из-под пальца, текст прыгает после загрузки картинки, баннер проталкивает контент вниз. Причина всегда одна - элемент занял место, которое не было для него зарезервировано. Лечение механическое: изображения и видео получают размеры, реклама и встраивания - минимальные контейнеры, шрифты - метрики запасного начертания, а динамический контент вставляется в собственные слои, а не поверх существующего:

.media {
  aspect-ratio: 16 / 9;
  max-width: 100%;
}
.banner-slot { min-height: 90px; }

Декларативное соотношение сторон резервирует место для любых медиа до их фактической загрузки, и страница перестаёт дышать на каждом скролле. Вставки поверх контента - тосты, чаты, подписки - появляются в собственных слоях, не проталкивая текст, потому что сдвиг посреди чтения читается пользователем как обида: он теряет место глазами и уверенность в сайте.

Анимации при этом проходят проверку на честность: движение к цели, а не от неё, и элементы не покидают свои контейнеры. Сдвиг по инициативе пользователя не штрафуется, поэтому раскрывающиеся меню и аккордеоны остаются в границах метрики, а вот автозапуск каруселей, двигающих контент, - нет.

Тест стабильности при этом входит в чек-лист релиза: сценарий прокрутки с медленной сетью на телефоне ловит прыжки, которые не видны на быстром стенде. Сдвиги - единственная метрика, чьи страдания видны пользователю буквально под пальцем, и их цена в доверии выше любых сотен миллисекунд задержки.

Инструменты диагностики показывают механику а не только цифры

Цифра метрики отвечает на вопрос плохо ли, но не отвечает на вопрос почему, и между ними работает диагностика. Водопад загрузки показывает критический путь главного содержимого: каждый ресурс с временем, блокировками и очерёдностью, и тормоз виден глазами за минуты. Записи производительности показывают длинные задачи отклика: стек вызовов, время процессора, и функции, съевшие кадры анимации. Разбор сдвигов подсвечивает элементы, изменившие положение, и их причины:

элемент метрики: hero.avif
задержка: загрузка началась после стилей (низкий приоритет)
лечение: preload + высокий приоритет, экономия ~800мс

Лабораторный стенд при этом подбирается под аудиторию: телефон среднего класса, медленная сеть, замедление процессора - профиль, в котором живут худшие половины визитов. Прогон на рабочем ноутбуке с быстрым каналом оптимизирует страницу для разработчика, и этот класс ошибок настолько распространён, что вошёл в учебники как отдельная слепота.

Диагностика завершается списком причин с ценой каждой: приоритет героя - час, разбиение задач - день, замена форматов - вечер. Сортировка по отношению эффекта к цене превращает список в план, и первая неделя работы даёт большую часть выигрыша. Отчёт пишется коротко - проблема, причина, лечение, эффект, - и такие записи за квартал образуют базу знаний, которая превращает производительность из ремесла отдельных героев в свойство процесса.

Полевые данные и бюджеты удерживают результат

Оптимизация без системы удержания - это разовая кампания с известным финалом: каждый релиз добавляет скрипт, картинку или виджет, и уже через два квартала метрики съезжают обратно в красную зону. Удержание строится двумя инструментами. Первый - мониторинг полевых данных по версиям релиза: регрессия видна в разрезе и связывается с изменением за минуты, а не за месяцы. Второй - бюджеты производительности в конвейере: превышение лимита веса и блокирующего кода останавливает сборку:

{
  "budgets": [
    { "type": "script", "maximum": 85000 },
    { "type": "transferSize", "maximum": 170000 }
  ]
}

Бюджеты защищают именно от медленной деградации - самого дорогого вида потерь, потому что у неё нет виноватого и нет события. Дисциплина бюджета превращает производительность из проекта в свойство, которое не требует обсуждений: лимиты известны, ответственность автоматической проверки очевидна, и спор о том, потянет ли страницу ещё один виджет, заканчивается до его установки.

Бюджеты при этом пересматриваются осознанно: сезонная акция с новым баннером получает временный лимит с датой возврата, а не тихое исключение навсегда. Дисциплина исключений отличает бюджет от лозунга, и конвейер напоминает о возврате сам.

Проверка зрелости оптимизации сводится к списку:

  1. полевые данные снимаются по всем трём метрикам на 75-м процентиле;
  2. герой страницы с приоритетом, современным форматом и размерами;
  3. длинные задачи разбиты, сторонние скрипты прошли аудит ценности;
  4. медиа резервируют место, вставки не проталкивают контент;
  5. бюджеты встроены в конвейер и блокируют регрессию;
  6. регрессии связываются с релизами и разбираются по горячим следам;
  7. целевая зелёная зона достигнута у устойчивой доли визитов.

Core Web Vitals в итоге - редкий случай, когда требования поисковиков и интересы пользователей совпадают буквально: быстрая, отзывчивая и стабильная страница одинаково ценна и поисковому роботу, и живому человеку. Оптимизация этих трёх цифр не требует ничего недостижимого - она требует последовательности: измерять честно, чинить известные механики, защищать достигнутое бюджетами. Сайты, прошедшие весь этот путь, замечают побочный эффект и за пределами поисковых позиций: поведение улучшается, конверсия растёт, и поддержка слышит меньше жалоб на торможение - лучшее подтверждение того, что метрики измеряют то, что действительно важно.