Дата публикации: 1 февраля 2023 г. Последнее обновление: 20 сентября 2026 г.
С момента запуска инициативы Core Web Vitals мы стремились оценивать реальное удобство сайта для пользователей, а не технические детали его создания или загрузки. Три показателя Core Web Vitals были созданы как пользовательские показатели – эволюция существующих технических показателей, таких как DOMContentLoaded или load, которые измеряли время, часто не связанное с тем, как пользователи воспринимали производительность страницы. Поэтому технология, на основе которой создан сайт, не должна влиять на оценку, если сайт работает хорошо.
Реальность всегда сложнее идеала, и популярная архитектура одностраничных приложений никогда не поддерживалась показателями Core Web Vitals в полной мере. Вместо того чтобы загружать отдельные веб-страницы по мере того, как пользователь перемещается по сайту, эти веб-приложения используют так называемую "мягкую навигацию", при которой контент страницы изменяется с помощью JavaScript. В таких приложениях иллюзия традиционной архитектуры веб-страниц поддерживается за счет изменения URL и добавления предыдущих URL в историю браузера, чтобы кнопки "Назад" и "Вперед" работали так, как ожидает пользователь.
Многие фреймворки JavaScript используют эту модель, но каждый по-своему. Поскольку это выходит за рамки того, что браузер традиционно понимает под "страницей", измерить это всегда было сложно: где провести границу между взаимодействием на текущей странице и рассмотрением этого как новой страницы?
Команда Chrome уже некоторое время работает над этой проблемой и стремится стандартизировать определение "мягкой навигации" и то, как для нее можно измерять показатели Core Web Vitals – аналогично тому, как измеряются сайты, реализованные в традиционной многостраничной архитектуре (MPA).
Мы внесли в предложение несколько улучшений на основе отзывов разработчиков и запустили два новых API производительности, которые помогут решить эту проблему в Chrome 151. Кроме того, мы добавили показатели мягкой навигации в Chrome User Experience Report (CrUX) в качестве экспериментальных.
Что такое мягкая навигация
Мы предлагаем следующее определение мягкой навигации:
- Навигация инициирована действием пользователя.
- В результате перехода URL, который видит пользователь, меняется.
- Взаимодействие приводит к видимой отрисовке.
Для некоторых сайтов это определение может привести к ложным срабатываниям (когда пользователи на самом деле не считают, что произошел переход) или ложноотрицательным результатам (когда пользователь считает, что переход произошел, несмотря на несоответствие этим критериям). Вы можете оставить отзыв в репозитории спецификации мягкой навигации.
Поддержка мягкой навигации в Инструментах разработчика
Мы добавили поддержку мягких переходов на панель производительности в DevTools в представлении Текущие показатели, а также в представлении трассировки с поддержкой статистики и маркеров:
Как Chrome реализует мягкую навигацию для веб-разработчиков?
После включения функции мягкой навигации (подробнее об этом в следующем разделе) Chrome изменит способ создания отчетов по некоторым показателям эффективности:
- После каждого обнаружения мягкой навигации будет генерироваться событие
soft-navigationPerformanceTiming. - Запись
soft-navigationбудет включатьnavigationId, новый URL в атрибутеname, а такжеinteractionIdинициирующего взаимодействия. - После взаимодействий, которые приводят к отрисовке контента, будет создана одна или несколько записей
interaction-contentful-paint. Она будет содержать записьlargestContentfulPaint, которую можно использовать для измерения Largest Contentful Paint (LCP) для мягких переходов. - Атрибут
navigationIdдобавляется к каждому из показателей времени (first-paint,first-contentful-paint,largest-contentful-paint,interaction-contentful-paint,first-input-delay,eventиlayout-shift). Он соответствует записи навигации, в которой было создано событие. Обратите внимание, что если эти записи охватывают программные переходы, они могут содержать предыдущий или следующийnavigationIdв зависимости от того, когда была создана запись. Подробнее об этом рассказывается в разделе Как сопоставить показатели с нужным URL. soft-navigationбудет включать функциюgetLargestInteractionContentfulPaint()для получения наибольшей записиinteraction-contentful-paintдля этой навигации. Затем это значение можно использовать в качестве начального LCP для этой навигации, а затем обновлять его по мере наблюдения за другими записямиinteraction-contentful-paintдля этого взаимодействия. Обратите внимание, что он заменяет атрибутlargestInteractionContentfulPaint, который был доступен в предыдущих экспериментах с источником.- Некоторые записи
interaction-contentful-paintмогут быть сделаны до мягкой навигации (если URL обновляется после отрисовки). В таких случаях функцияgetLargestInteractionContentfulPaint()позволяет избежать буферизации и просмотра старых записей после завершения плавной навигации. Обратите внимание, что запись, возвращаемаяgetLargestInteractionContentfulPaint(), является точной копией самой большой записиinteraction-contentful-paintна момент ее создания, поэтому в этой записи мог использоваться предыдущийnavigationId, поскольку именно тогда произошла отрисовка, но эти отрисовки должны измеряться по сравнению с новымnavigationId. - Запись
soft-navigationтакже будет содержатьpaintTimeиpresentationTimeв качестве FCP для этой навигации. - Обратите внимание, что записи
interaction-contentful-paintтакже будут создаваться после дальнейших взаимодействий, но LCP для URL должен быть ограничен записямиinteraction-contentful-paint, которые соответствуютinteractionIdплавной навигации, чтобы исключить их, а также только свойствамиlargestContentfulPaintв них.
Эти изменения позволят измерять Core Web Vitals и некоторые связанные с ними диагностические показатели для каждой навигации по страницам, хотя есть некоторые нюансы, которые необходимо учитывать.
Каковы последствия включения мягких переходов в Chrome?
После включения этой функции владельцам сайтов необходимо учитывать следующее:
- Отслеживание записей
soft-navigationпозволяет разбивать записи об эффективности на отдельные навигации. - Показатели CLS и INP уже можно сегментировать по вашему усмотрению, а не измерять на протяжении всего жизненного цикла страницы. Однако функция плавного перехода позволяет стандартизировать измерение независимо от используемой технологии.
- Запись
largest-contentful-paintзавершается при взаимодействии (которое необходимо для начала мягкой навигации), поэтому ее можно использовать только для измерения LCP при начальной "жесткой" навигации. Это означает, что при измерении мягких переходов ничего не изменится, поэтому LCP для начальной загрузки страницы с жестким переходом можно измерить, как и всегда. - Новая запись
interaction-contentful-paint, которая будет создаваться при взаимодействиях, может использоваться для измерения LCP для мягких навигаций путем просмотра свойстваlargestContentfulPaintвнутри нее, но есть некоторые соображения по поводу того, как использовать эту запись, которые мы обсудим в этой статье. - Обратите внимание, что не все пользователи будут поддерживать эту функцию мягкой навигации, особенно те, кто использует другие браузеры или версии Chrome до 151. Учтите, что некоторые пользователи могут не передавать показатели, связанные с мягкой навигацией, даже если они передают показатели Core Web Vitals.
Уточните у своего поставщика RUM, поддерживает ли он измерение Core Web Vitals с помощью плавной навигации. Многие планируют протестировать новый стандарт и будут учитывать предыдущие соображения. Некоторые поставщики также позволяют ограниченно измерять показатели эффективности на основе собственных эвристических методов.
Подробнее о том, как измерять показатели для мягких переходов, читайте в разделе Измерение показателей Core Web Vitals для мягких переходов.
Как включить мягкую навигацию в Chrome?
Функция мягкой навигации включена по умолчанию начиная с Chrome 151.
Обнаружение поддержки Soft Navigations API
Чтобы проверить, поддерживается ли API, можно использовать следующий код:
if (PerformanceObserver.supportedEntryTypes.includes('soft-navigation')) {
// Monitor Soft Navigations
}
Другой вариант:
if ('SoftNavigationEntry' in window) {
// Monitor Soft Navigations
}
Как измерить плавную навигацию?
Если поддерживается, показатели можно включать в отчеты с помощью API PerformanceObserver, как и другие показатели. Однако при работе с этими показателями необходимо учитывать некоторые дополнительные факторы.
Отчеты о мягкой навигации
Для отслеживания мягкой навигации можно использовать PerformanceObserver. Ниже приведен пример фрагмента кода, который регистрирует записи о плавной навигации в консоли, включая предыдущие переходы на этой странице с помощью параметра buffered:
const observer = new PerformanceObserver(console.log);
observer.observe({ type: "soft-navigation", buffered: true });
Это можно использовать для завершения показателей страницы за весь срок службы для предыдущей навигации.
Показатели в отчетах сопоставляются с нужными URL.
При обнаружении плавного перехода основные интернет-показатели предыдущей страницы должны быть зафиксированы и затем переданы для предыдущего URL, а для нового URL должен быть запущен новый мониторинг.
Атрибут name соответствующей записи soft-navigation будет содержать новый URL, для которого нужно регистрировать показатели, а navigationId будет уникальной ссылкой для этой навигации (поскольку один и тот же URL может посещаться несколько раз за время существования одностраничного приложения).
Это значение должно быть задано для каждой записи soft-navigation и использоваться для отчетных показателей до получения следующей записи soft-navigation.
Сообщите правильный URL для interaction-contentful-paint
При расчете LCP на основе записей interaction-contentful-paint необходимо учитывать дополнительные факторы, поскольку не все записи interaction-contentful-paint должны сопоставляться с помощью navigationId и регистрироваться как LCP для этого URL:
- Первая проблема заключается в том, что записи
interaction-contentful-paintмогут быть созданы до мягкой навигации, если отрисовка происходит до обновления URL. В таких случаяхnavigationIdбудет относиться к старому URL. Если URL-адрес обновляется первым, то отрисовка завершит мягкую навигацию, и в этом случае сначала будет создана записьsoft-navigation, аinteraction-contentful-paintбудет иметь новый URL-адрес. - Вторая проблема заключается в том, что
interaction-contentful-paintзаписи будут по-прежнему создаваться для новых взаимодействий, поскольку область действия этого показателя эффективности выходит за рамки LCP для мягких переходов. Мы хотим учитывать только отрисовки для загрузки мягкой навигации для LCP, а не для последующих взаимодействий.
Поэтому для сопоставления записей interaction-contentful-paint с soft-navigation-entries и получения правильного URL следует использовать interactionId, а не navigationId. Это позволит обработать все записи со старыми значениями navigationId, а также отфильтровать записи interaction-contentful-paint, которые не должны учитываться при расчете LCP.
Кроме того, сначала нужно обработать функцию getLargestInteractionContentfulPaint() записей soft-navigation, чтобы обработать записи interaction-contentful-paint, которые произошли до того, как было создано событие soft-navigation entries.
Получение startTime мягких навигаций
Все временные показатели эффективности, в том числе для мягких переходов, и записи, используемые для расчета Core Web Vitals, регистрируются как время с момента первоначальной жесткой навигации по страницам. Поэтому время начала мягкой навигации нужно вычитать из времени загрузки при мягкой навигации (например, LCP), чтобы получать показатели относительно времени мягкой навигации.
Время начала навигации можно получить аналогичным образом, сопоставив его с соответствующей записью soft-navigation и используя ее startTime.
startTime – время первого взаимодействия (например, нажатия кнопки), которое инициировало мягкую навигацию. Это отличается от жестких переходов, когда время начала – это момент, когда новая страница фиксируется в браузере и после того, как выполняется часть кода обработчика событий. Время начала мягкой навигации также включает код обработчика событий, поскольку мы измеряем время с момента начала взаимодействия.
Измерение показателей Core Web Vitals для каждого плавного перехода
Чтобы измерить показатели Core Web Vitals, отслеживайте записи soft-navigation и сбрасывайте показатели при их получении. FCP может быть зафиксирована на основе presentationTime, а LCP – на основе getLargestInteractionContentfulPaint(). INP и CLS должны быть инициализированы как 0, как и при загрузке страницы.
После этого показатели LCP, INP и CLS можно измерять и отслеживать как обычно (за исключением использования interaction-contentful-paint для LCP, если interactionId совпадает). Как упоминалось выше, с помощью атрибута interactionId можно присваивать названия записям, относящимся к URL.
Время по-прежнему будет возвращаться относительно исходного времени начала навигации. Чтобы рассчитать LCP для мягкой навигации, нужно взять время interaction-contentful-paint и вычесть из него время начала мягкой навигации, как описано выше.
Некоторые показатели традиционно измеряются на протяжении всего жизненного цикла страницы. Например, LCP может меняться до тех пор, пока не произойдет взаимодействие. Значения CLS и INP могут обновляться до тех пор, пока пользователь не покинет страницу, независимо от его действий. Поэтому показатели предыдущей навигации должны быть завершены по мере возникновения каждой новой программной навигации. Это означает, что при измерении показателей Core Web Vitals с мягкими переходами исходные показатели "жестких" переходов могут быть зафиксированы раньше, чем обычно.
Аналогично, когда начинается измерение показателей для новой мягкой навигации, показатели необходимо сбросить или повторно инициализировать и рассматривать как новые показатели, не учитывая значения, которые были установлены для предыдущих страниц. Это означает, что данные о том, что считать "самым крупным" контентом, взаимодействием до следующей отрисовки или сдвигом макета, сбрасываются, чтобы можно было начать измерения заново.
Как следует обрабатывать контент, который остается неизменным между переходами?
LCP для мягких переходов (рассчитывается на основе interaction-contentful-paint) будет измерять только новые отрисовки и только отрисовки, связанные с взаимодействием, которое вызвало переход. В результате значение LCP при холодной загрузке может отличаться от значения при мягкой загрузке.
Например, на странице есть большой баннер, который является элементом LCP, но текст под ним меняется при каждом плавном переходе. При начальной загрузке страницы в качестве элемента LCP будет помечено изображение баннера, и время LCP будет рассчитываться на его основе. При последующих мягких переходах текст под ним будет самым большим элементом, нарисованным после мягкого перехода, и станет новым элементом LCP. Однако если страница загружается по ссылке на контент в URL программной навигации, то изображение баннера будет новым элементом отрисовки и поэтому может считаться элементом LCP.
Аналогично, анимация может постоянно обновлять часть страницы, не связанную с какой-либо мягкой навигацией. Любые новые отрисовки, связанные с этой фоновой анимацией, не будут учитываться при расчете LCP для нового плавного перехода. Однако они могут учитываться при расчете LCP, если страница была перезагружена с этого URL.
Как видно из этих примеров, элемент LCP для мягкой навигации может регистрироваться по-разному в зависимости от того, как загружается страница. Точно так же загрузка страницы с анкерной ссылкой ниже на странице может привести к другому элементу LCP для жесткой навигации.
Как измерить TTFB
Время до первого байта (TTFB) при обычной загрузке страницы – это время, за которое возвращаются первые байты исходного запроса.
В случае с мягкой навигацией все сложнее. Нужно ли измерять первый запрос, сделанный для новой страницы? Что если весь контент уже есть в приложении и дополнительных запросов нет? Что если этот запрос будет сделан заранее с помощью предварительной выборки? Что если запрос не связан с мягкой навигацией с точки зрения пользователя (например, это запрос аналитики)?
Более простой способ – сообщать о нулевом значении TTFB для мягких переходов, как мы рекомендуем делать при восстановлении из возвратного кеша. Именно этот метод используется в библиотеке web-vitals для мягкой навигации, и мы рекомендуем его для этого показателя.
Нужно ли измерять показатели Core Web Vitals обоими способами?
Хотя эти новые API ограничены только браузерами на основе Chromium, сайты могут захотеть измерять оба показателя, разделяя их по мягким и жестким переходам. Это позволит сравнивать данные в разных браузерах и отслеживать тенденции.
Для LCP это означает, что при текущем подходе учитываются только записи largest-contentful-paint, а при новом – и largest-contentful-paint, и interaction-contentful-paint.
Для CLS и INP это означает, что нужно измерять их на протяжении всего жизненного цикла страницы, как это делается сейчас, и отдельно разбивать временную шкалу по мягким переходам, чтобы измерять отдельные значения CLS и INP для нового.
В этом случае показатели нужно будет передавать и сохранять дважды.
Как использовать библиотеку web-vitals для измерения основных интернет-показателей при мягкой навигации
Проще всего учесть все нюансы, используя библиотеку JavaScript web-vitals, которая поддерживает плавную навигацию начиная с версии 6.0.0. Это можно измерить следующим образом (замените doTraditionalProcessing и doSoftNavProcessing соответствующими значениями):
import {
onTTFB,
onFCP,
onLCP,
onCLS,
onINP,
} from 'https://unpkg.com/web-vitals@soft-navs/dist/web-vitals.js?module';
function doTraditionalProcessing(callback) {
...
}
function doSoftNavProcessing(callback) {
...
}
onTTFB(doTraditionalProcessing);
onFCP(doTraditionalProcessing);
onLCP(doTraditionalProcessing);
onCLS(doTraditionalProcessing);
onINP(doTraditionalProcessing);
onTTFB(doSoftNavProcessing, {reportSoftNavs: true});
onFCP(doSoftNavProcessing, {reportSoftNavs: true});
onLCP(doSoftNavProcessing, {reportSoftNavs: true});
onCLS(doSoftNavProcessing, {reportSoftNavs: true});
onINP(doSoftNavProcessing, {reportSoftNavs: true});
Библиотека web-vitals также гарантирует, что показатели будут соотнесены с правильным URL, как описано выше, поскольку в записях, предоставляемых обратному вызову, есть и navigationId, и navigationURL.
Библиотека web-vitals сообщает следующие показатели для мягкой навигации:
| Показатель | Сведения |
|---|---|
| TTFB | Значение по умолчанию – 0. |
| FCP | Время первой отрисовки контента относительно времени начала мягкой навигации, начиная с взаимодействия, которое запустило мягкую навигацию. Существующие отрисовки, оставшиеся от предыдущей навигации или не связанные с взаимодействием, не учитываются. |
| LCP | Время отрисовки самого крупного контента относительно времени начала мягкой навигации, начиная с взаимодействия, которое запустило мягкую навигацию. Существующие отрисовки, оставшиеся от предыдущей навигации, не связаны с взаимодействием и не учитываются. Как обычно, это значение может обновляться до тех пор, пока пользователь не покинет страницу (или не выполнит мягкую навигацию), поскольку только тогда можно будет окончательно определить LCP. |
| INP | INP между переходами. Как обычно, это значение может обновляться до тех пор, пока пользователь не покинет страницу (или не выполнит мягкую навигацию), поскольку только тогда можно будет окончательно определить INP. Если взаимодействий не было, значение 0 не указывается. Обратите внимание, что взаимодействие, вызывающее мягкую навигацию, обычно связано с предыдущей навигацией (из которой осуществляется переход), а не с новой навигацией (к которой осуществляется переход), поскольку для мягкой навигации требуется первая отрисовка. Это похоже на жесткую навигацию, когда клик по ссылке может иметь INP, но который будет связан со страницей, на которой произошел клик. |
| CLS | Самый большой интервал между сменами навигации. Как обычно, это значение может обновляться до тех пор, пока пользователь не покинет страницу (или не выполнит мягкую навигацию), поскольку только тогда можно будет окончательно определить CLS. Обратите внимание, что совокупный сдвиг макета, связанный с событием навигации, может быть исключен (если он происходит в течение 500 мс после взаимодействия), связан с предыдущей навигацией (если сдвиг происходит до обновления URL) или связан с новой навигацией (если сдвиг происходит после завершения мягкой навигации). |
Станут ли эти изменения частью показателей Core Web Vitals?
Конечная цель – предоставить средства для более точного измерения производительности, воспринимаемой реальными пользователями. Да, мы планируем включить эти показатели в Core Web Vitals, чтобы они отображались во всех инструментах после запуска API.
Как мягкие переходы будут отражаться в CrUX?
Мы запустили экспериментальные версии показателей Core Web Vitals в CrUX. Они завершают CLS и INP для жесткой навигации после первой мягкой навигации, а также включают дополнительные показатели LCP, CLS и INP для каждой мягкой навигации. Мы планируем перевести эти экспериментальные показатели в стабильные в мае 2027 г. Дополнительную информацию можно найти в записи блога Экспериментальные показатели мягкой навигации теперь доступны в CrUX.
Как обрабатывать мягкие переходы в других браузерах?
Мягкие переходы сложно обнаружить программно в браузерах, которые не поддерживают API. Именно поэтому мы работали над этим API.
Вы можете использовать Navigation API, чтобы отслеживать изменения URL. Это позволит сегментировать INP по URL (и CLS, хотя сейчас этот показатель доступен только в Chromium, поэтому не будет измеряться в любом случае). Однако это не относится к показателям отрисовки (FCP и LCP), которые можно определить только приблизительно.
В то же время мы считаем, что данные, предоставляемые этим API, слишком ценны, чтобы их игнорировать, как при измерении времени мягкой навигации, так и при сопоставлении показателей с правильной навигацией. Мы рекомендуем использовать этот новый API, несмотря на то, что в настоящее время он поддерживается не всеми браузерами. Как и в случае с Core Web Vitals, выявленные проблемы и решения, направленные на повышение производительности, скорее всего, затронут все браузеры, даже если сейчас они видны только в браузерах на основе Chromium.
Мы продолжим работу над стандартизацией и будем взаимодействовать с другими поставщиками браузеров, чтобы показать важность этого API.
Как оставить отзыв
Мы активно собираем отзывы об этом API на следующих ресурсах:
- Отзывы об API можно оставлять в виде сообщений о проблемах на GitHub.
- Если вы обнаружили ошибку в реализации Chromium, которой нет в списке известных проблем, сообщите о ней в системе отслеживания ошибок Chrome.
- Общие отзывы о Web Vitals можно отправлять на адрес web-vitals-feedback@googlegroups.com.
Если вы сомневаетесь, не беспокойтесь. Мы рады получить отзыв в любом месте и с удовольствием разберемся с проблемами и перенаправим их в нужное место.
Журнал изменений
В процессе разработки этого API в него было внесено много изменений, больше, чем в стабильные API. Подробную информацию можно найти в журнале изменений плавных переходов.
Заключение
Функция Soft Navigations – это интересный подход к тому, как инициатива Core Web Vitals может развиваться для измерения распространенного шаблона в современном интернете, который отсутствует в наших показателях. Мы получили множество отзывов от веб-сообщества и видим большой потенциал в этом API.
Благодарности
Значок: Jordan Madrid, Unsplash
Эта работа – продолжение проекта, начатого Йоавом Вайсом (Yoav Weiss), когда он работал в Google. Мы благодарим Йоава за его работу над этим API.