Показатели Core Web Vitals — Примеры
Пример 1 — Главное изображение отложено и без размеров
Самый большой элемент на странице грузится отложенно и не объявляет размеров, поэтому появляется поздно, а текст под ним прыгает при его приходе. Назовите два показателя, которым это вредит, и исправьте разметку.
<img src="/hero.avif" loading="lazy" alt="Мастерская на закате" />
Решение
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high" />
<img src="/hero.avif" width="1600" height="900" alt="Мастерская на закате" />
Largest Contentful Paint измеряет, когда появляется самый большой видимый элемент, а loading="lazy" намеренно откладывает именно этот элемент. Эта директива предназначена для изображений ниже первого экрана, где она экономит трафик, не роняя показатель. Предзагрузка и повышенный приоритет заставляют файл обнаружиться и скачаться раньше — это обычное единичное исправление позднего главного изображения. Cumulative Layout Shift измеряет движение, которого пользователь не вызывал, а изображение без объявленных размеров не резервирует места, поэтому каждая строка под ним сдвигается вниз при его появлении. width и height дают браузеру соотношение сторон для резервирования, тогда как отображаемый размер по-прежнему задаёт CSS. Два атрибута, два показателя.
Пример 2 — Обработчик, блокирующий каждое действие
Одна кнопка запускает цикл, который фильтрует десять тысяч записей и синхронно перерисовывает список. Интерфейс игнорирует клики почти целую секунду. Скажите, какой это показатель и почему страдают и несвязанные действия, затем дайте браузеру отрисовать между кусками.
button.addEventListener("click", () => {
const matches = records.filter((r) => r.name.includes(query));
render(matches); // 400мс работы основного потока одной задачей
});
Решение
button.addEventListener("click", async () => {
const matches = records.filter((r) => r.name.includes(query));
for (let i = 0; i < matches.length; i += 100) {
render(matches.slice(i, i + 100));
await new Promise((resolve) => setTimeout(resolve, 0));
}
});
Interaction to Next Paint измеряет задержку между нажатием и ближайшим кадром, который нарисует браузер. Задача в несколько сотен миллисекунд держит основной поток, так что ничего не может быть обработано до её конца — включая действия, не имеющие отношения к этому обработчику. Поэтому кажется, что зависла вся страница, а не одна кнопка. Уступая управление между кусками, вы возвращаете его браузеру, чтобы он мог отрисовать и разобрать ввод, и рендерер затем рисует постепенно, а не один раз в конце. Измерение, подтверждающее исправление, — дорожка основного потока в записи, а не время настенных часов в цикле.