Оптимизация производительности веб-приложений в 2026: Core Web Vitals, INP и новые метрики
Оптимизация производительности веб-приложений в 2026: Core Web Vitals, INP и новые метрики
Производительность веб-приложений перестала быть опциональным улучшением — сегодня это прямой фактор ранжирования в поисковых системах и, что важнее, определяющий фактор удержания пользователей. По данным Google, 53% посетителей покидают сайт, если он загружается дольше трёх секунд, а каждая секунда задержки снижает конверсию в среднем на 7%. В 2026 году, когда мобильный трафик составляет более 60% всего веб-трафика, а пользователи ожидают мгновенного отклика от каждого взаимодействия, производительность становится конкурентным преимуществом.
Core Web Vitals — это набор метрик, созданных Google для количественной оценки пользовательского опыта. В отличие от синтетических метрик вроде Speed Index или Time to Interactive, Core Web Vitals измеряются на реальных устройствах реальных пользователей через Chrome User Experience Report (CrUX). Именно эти данные Google использует как сигнал ранжирования. В этой статье мы разберём, что изменилось в 2026 году, как оптимизировать каждую из трёх метрик и какие инструменты помогут держать производительность под контролем.
Что изменилось в 2026: INP вместо FID
Самое значительное изменение в экосистеме Core Web Vitals произошло в марте 2024 года, когда Google официально заменил First Input Delay (FID) на Interaction to Next Paint (INP). К 2026 году этот переход полностью завершился, и теперь INP — обязательная метрика для прохождения оценки Page Experience.
Чем INP отличается от FID
FID измерял только задержку перед обработкой самого первого взаимодействия пользователя со страницей. Это была крайне ограниченная метрика: если первое взаимодействие происходило быстро, а последующие — нет, FID этого не показывал. INP же оценивает каждое взаимодействие на протяжении всей жизни страницы: клики, нажатия клавиш, тапы на мобильных устройствах. Итоговое значение — это наихудшее взаимодействие на 75-м перцентиле.
На практике это означает, что INP значительно жёстче. Если раньше сайт мог «проскочить» метрику интерактивности за счёт удачного первого взаимодействия, то теперь Google оценивает отзывчивость на всём протяжении сессии. По данным CrUX на начало 2026 года, 43% сайтов всё ещё не проходят порог INP в 200 мс, что делает INP самой проваливаемой метрикой из трёх.
Актуальные пороговые значения
| Метрика | Хорошо | Требует улучшений | Плохо |
|---------|--------|-------------------|-------|
| LCP (загрузка) | ≤ 2,5 с | 2,5–4,0 с | > 4,0 с |
| INP (интерактивность) | ≤ 200 мс | 200–500 мс | > 500 мс |
| CLS (стабильность) | ≤ 0,1 | 0,1–0,25 | > 0,25 |
Процент прохождения каждой метрики выглядит так: CLS — 78% сайтов проходят порог, LCP — 68%, INP — всего 57%. При этом сайты, проходящие все три метрики, имеют на 24% ниже показатель отказов и значимо лучшие позиции в органической выдаче.
LCP: как ускорить загрузку основного контента
Largest Contentful Paint измеряет время от начала навигации до момента, когда самый крупный видимый элемент в области просмотра полностью отрендерен. Чаще всего это hero-изображение (72% страниц), крупный заголовок (18%) или фоновое изображение (7%). Целевой порог — 2,5 секунды на соединении 4G.
Оптимизация изображений — основа LCP
Изображения остаются самым тяжёлым компонентом большинства веб-страниц, и именно их оптимизация даёт наибольший прирост LCP. Первым делом необходимо определить, какой элемент является LCP на вашей странице — это можно сделать через Chrome DevTools (Performance panel, маркер LCP) или через Performance Observer API в коде:
const observer = new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP element:', lastEntry.element);
console.log('LCP time:', lastEntry.startTime);
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
После того как LCP-элемент найден, применяем следующие техники:
Прелоад LCP-ресурса. Добавьте в <head> документа тег preload для LCP-изображения. Это указывает браузеру начать загрузку изображения немедленно, параллельно с CSS и JavaScript, а не ждать, пока парсер HTML дойдёт до соответствующего тега <img>:
<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high" />
Современные форматы. AVIF обеспечивает сжатие на 30–50% лучше JPEG при том же визуальном качестве. WebP остаётся безопасным fallback с практически универсальной поддержкой браузеров. Используйте элемент <picture> для бесшовной отдачи форматов:
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero image"
width="1200" height="630"
fetchpriority="high" decoding="async" />
</picture>
Не лените LCP-изображение. Атрибут loading="lazy" на LCP-элементе — одна из самых частых ошибок. LCP-изображение должно загружаться немедленно, без lazy loading. Используйте loading="eager" в явном виде и fetchpriority="high".
Серверное время отклика
LCP не может быть быстрее, чем Time to First Byte (TTFB). Если ваш сервер отвечает за 800 мс, то потолок LCP — 800 мс до начала любой загрузки ресурсов. Используйте CDN с кэшированием на границе сети, SSR или статическую генерацию страниц и оптимизируйте запросы к базе данных. Целевое значение TTFB — менее 200 мс.
Шрифты и критический CSS
Веб-шрифты блокируют рендеринг текста по умолчанию. Если LCP-элемент — текстовая строка, загрузка шрифта напрямую влияет на LCP. Прелоадьте критические шрифты и используйте font-display: swap, чтобы показать системный шрифт немедленно, а затем заменить его на кастомный после загрузки:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap;
}
Также инлайните критический CSS — стили, необходимые для отрисовки контента «над сгибом», вставляйте непосредственно в <head>, а остальной CSS подгружайте асинхронно. Это может сократить LCP на 300–800 мс на медленных соединениях.
INP: метрика, которую сложнее всего оптимизировать
Interaction to Next Paint измеряет полное время от момента взаимодействия пользователя до отрисовки следующего кадра. INP состоит из трёх фаз: задержка ввода (input delay), время обработки (processing time) и задержка отрисовки (presentation delay).
Пользователь → [Задержка ввода] → Обработка → [Время обработки] → Отрисовка → [Задержка отрисовки] → Визуальное обновление
Фаза 1: задержка ввода
Самая частая причина высокого INP — заблокированный главный поток. Когда браузер занят выполнением длительной JavaScript-задачи, он не может обработать новое взаимодействие пользователя. Основные источники блокировки — тяжёлые сторонние скрипты (аналитика, чат-виджеты, рекламные скрипты) и гидратация JavaScript-фреймворков.
Решение: разбивайте длинные задачи. Каждая задача дольше 50 мс считается длинной и блокирует главный поток. Используйте scheduler.yield() или setTimeout для разбивки тяжёлых вычислений на микро-задачи:
// Плохо: одна длинная задача блокирует поток
function processLargeData(data) {
data.forEach(item => {
// Тяжёлые вычисления...
});
}
// Хорошо: разбиваем на порции по 50 элементов
async function processLargeDataOptimized(data) {
const chunks = chunkArray(data, 50);
for (const chunk of chunks) {
await new Promise(resolve => setTimeout(resolve, 0));
chunk.forEach(item => { /* Вычисления */ });
}
}
Фаза 2: время обработки
Время обработки — это фактическое выполнение обработчиков событий (click, keypress, tap). Дорогие DOM-операции, синхронные обновления состояния и принудительные перерасчёты макета внутри обработчиков — главные враги этой фазы.
Решение: минимизируйте DOM-мутации в обработчиках. Используйте requestAnimationFrame для визуальных обновлений и батчите изменения состояния. В React применяйте useDeferredValue для отложенных обновлений с низким приоритетом и React.memo для предотвращения лишних ререндеров:
// Плохо: синхронные DOM-операции в обработчике
button.addEventListener('click', () => {
const height = element.offsetHeight;
element.style.height = height + 100 + 'px';
for (let i = 0; i < items.length; i++) {
document.getElementById('item-' + i).classList.add('active');
}
});
// Хорошо: асинхронные обновления через requestAnimationFrame
button.addEventListener('click', () => {
requestAnimationFrame(() => {
element.style.height = element.offsetHeight + 100 + 'px';
});
requestAnimationFrame(() => {
items.forEach(item => item.classList.add('active'));
});
});
Фаза 3: задержка отрисовки
Время между завершением обработчиков и фактической отрисовкой пикселей на экране. Большие DOM-деревья, сложные CSS-селекторы и избыточная работа по композиции слоёв увеличивают эту фазу.
Решение: уменьшайте DOM-дерево и упрощайте CSS-селекторы. Используйте свойство content-visibility: auto для контента за пределами экрана — браузер будет пропускать рендеринг таких секций до момента скролла. Это может ускорить начальную отрисовку в несколько раз на страницах с длинным контентом.
Отладка INP
Для отладки INP используйте библиотеку web-vitals с атрибуцией:
import { onINP } from 'web-vitals/attribution';
onINP((metric) => {
console.log('INP value:', metric.value, 'ms');
console.log('Element:', metric.attribution.interactionTarget);
console.log('Input delay:', metric.attribution.inputDelay, 'ms');
console.log('Processing:', metric.attribution.processingDuration, 'ms');
console.log('Presentation:', metric.attribution.presentationDelay, 'ms');
});
В Chrome DevTools откройте панель Performance, включите «Web Vitals» в настройках и запишите сессию с взаимодействиями. Каждое взаимодействие появится как маркер на таймлайне с детальным разбивкой по трём фазам.
CLS: устраняем неожиданные сдвиги макета
Cumulative Layout Shift измеряет визуальную стабильность страницы — насколько неожиданно сдвигается контент в процессе загрузки. Целевой порог — менее 0,1. Сдвиги макета особенно критичны на мобильных устройствах, где они приводят к случайным нажатиям на рекламу или не те ссылки.
Явные размеры для всех медиа-элементов
Самая частая причина CLS — изображения и видео без явно указанных ширины и высоты. Браузер не может зарезервировать место для такого контента, и после его загрузки весь контент ниже сдвигается:
<!-- Плохо: без размеров → сдвиг макета -->
<img src="/photo.jpg" alt="Фото" />
<!-- Хорошо: явные размеры → браузер резервирует место -->
<img src="/photo.jpg" alt="Фото" width="800" height="600" loading="lazy" />
Для адаптивных изображений используйте CSS-свойство aspect-ratio. Оно позволяет задать соотношение сторон, а браузер сам вычислит высоту на основе ширины:
.hero-image {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
Веб-шрифты и их влияние на CLS
При использовании font-display: swap браузер сначала отображает текст запасным шрифтом, а затем перерисовывает его кастомным. Если метрики шрифтов различаются, текстовая строка меняет размер и сдвигает окружающий контент. Решение — подгонять метрики запасного шрифта под кастомный через CSS-дескриптор size-adjust:
@font-face {
font-family: 'Inter Fallback';
src: local('Arial');
size-adjust: 107.64%;
ascent-override: 90%;
descent-override: 22.43%;
line-gap-override: 0%;
}
body {
font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;
}
В Next.js эта настройка автоматически генерируется через next/font — ещё один аргумент в пользу фреймворка.
Рекламные места и динамический контент
Рекламные баннеры, формы подписки и cookie-банеры — частые источники CLS. Для рекламных слотов всегда резервируйте место через min-height и min-width. Cookie-банерам задавайте position: fixed, чтобы они накладывались поверх контента, а не сдвигали его:
.ad-slot {
min-height: 250px;
width: 300px;
background: #f4f4f5;
}
.cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 50;
}
Инструменты измерения и мониторинга
Google использует для ранжирования полевые данные из CrUX (Chrome User Experience Report), поэтому ваши лабораторные тесты важны лишь настолько, насколько они предсказывают реальный пользовательский опыт. Необходимо использовать комбинацию лабораторных и полевых инструментов.
Лабораторные инструменты
- Lighthouse — базовый аудит производительности с рекомендациями. Встроен в Chrome DevTools.
- PageSpeed Insights — объединяет лабораторные данные Lighthouse с полевыми данными CrUX для конкретной страницы.
- Chrome DevTools Performance panel — покадровый анализ рендеринга с детальной атрибуцией INP.
- WebPageTest — продвинутый анализ водопада загрузки с реальных устройств и соединений.
Полевые инструменты (Real User Monitoring)
- Google Search Console — отчёт Core Web Vitals показывается прохождение метрик по группам URL на основе 28-дневного окна CrUX.
- Библиотека web-vitals — отправляйте реальные метрики с ваших страниц в систему аналитики.
- Vercel Analytics — мониторинг Web Vitals для проектов на Next.js.
- SpeedCurve / DebugBear — коммерческие решения с детальными дашбордами и оповещениями.
Настройка сбора метрик в продакшне
import { onCLS, onINP, onLCP } from 'web-vitals/attribution';
function sendToAnalytics(metric) {
const body = {
name: metric.name,
value: metric.value,
rating: metric.rating,
page: window.location.pathname,
};
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/analytics/vitals', JSON.stringify(body));
}
}
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
Performance-бюджеты и CI/CD
Оптимизация производительности — не разовая задача, а непрерывный процесс. Без формальных бюджетов производительность неизбежно деградирует по мере добавления новых функций, скриптов и изображений.
Рекомендованные бюджеты на 2026 год
| Категория | Целевое значение |
|-----------|-----------------|
| JavaScript (сжатый) | < 300 КБ |
| CSS (сжатый) | < 80 КБ |
| Hero-изображение | < 200 КБ |
| Общий вес страницы | < 1,5 МБ |
| Сторонних скриптов | < 5 |
| LCP | < 2,0 с (буфер относительно порога 2,5 с) |
| INP | < 150 мс (буфер относительно порога 200 мс) |
| CLS | < 0,05 (буфер относительно порога 0,1) |
Интеграция с CI/CD
Lighthouse CI запускает аудит на каждый pull request и может завершать сборку ошибкой, если метрики падают ниже установленных порогов. Это предотвращает попадание регрессий в продакшн:
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.9 }],
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"total-byte-weight": ["warning", { "maxNumericValue": 1500000 }]
}
}
}
}
Заключение
Производительность веб-приложений в 2026 году — это не просто техническая метрика, а бизнес-показатель, напрямую влияющий на конверсию, удержание пользователей и позиции в поисковой выдаче. Переход от FID к INP сделал метрику интерактивности значительно более требовательной, и 43% сайтов всё ещё не готовы к этому изменению.
Ключевые выводы из материала:
- LCP требует системной оптимизации на четырёх уровнях: изображения, серверный отклик, шрифты и критический CSS. Начните с прелоада LCP-изображения и конвертации в AVIF.
- INP — самая сложная метрика. Её улучшение требует пересмотра JavaScript-архитектуры: разбивки длинных задач, оптимизации обработчиков событий и уменьшения DOM-дерева.
- CLS — наиболее прямолинейная метрика: явные размеры для всех медиа, резервирование места под динамический контент и правильная загрузка шрифтов решают 90% проблем.
- Мониторинг должен быть непрерывным. Настройте сбор полевых метрик через web-vitals.js, интегрируйте Lighthouse CI в CI/CD и следите за CrUX в Google Search Console.
Начните с аудита текущего состояния вашего сайта через PageSpeed Insights, определите самую проблемную метрику и примените соответствующие техники из этой статьи. Производительность — это инвестиция, которая окупается каждый день в виде лучшего пользовательского опыта и более высоких позиций в поиске.
Часто задаваемые вопросы
Что такое INP и чем он отличается от FID?
INP (Interaction to Next Paint) измеряет задержку всех взаимодействий пользователя со страницей, а не только первого, как было в FID. INP оценивает полный цикл: от момента клика до отрисовки результата, включая задержку ввода, время обработки и время отрисовки.
Какой инструмент лучше всего подходит для измерения Core Web Vitals?
Для быстрой диагностики используйте PageSpeed Insights — он показывает и лабораторные, и полевые данные. Для постоянного мониторинга в продакшне настройте библиотеку web-vitals.js и отправляйте метрики в свою систему аналитики.
Влияют ли Core Web Vitals на позиции в Google напрямую?
Да, Core Web Vitals входят в сигнал ранжирования Page Experience. Google использует полевые данные CrUX на 75-м перцентиле для оценки. При прочих равных условиях сайты с лучшими Core Web Vitals получают преимущество в выдаче.
Как часто нужно проверять Core Web Vitals?
Мониторинг должен быть непрерывным. Полевые данные в Google Search Console обновляются с задержкой в 28 дней, но вы можете настроить оповещения в реальном времени через RUM-решения. Проверяйте CrUX-отчёт ежемесячно, а лабораторные тесты — на каждый pull request через Lighthouse CI.
Что делать, если INP высокий, а сайт загружается быстро?
Высокий INP при быстрой загрузке — типичный сценарий для SPA-приложений и сайтов с тяжёлыми сторонними скриптами. Проверьте длинные задачи в Chrome DevTools Performance, проаудируйте сторонние скрипты (чат-виджеты, аналитику) и примените разбивку задач через scheduler.yield().