Список рекомендаций по Core Web Vitals (Part 2)
В прошлой части статьи по оптимизации веб-приложений мы с вами говорили об основных рекомендациях ребят из Google, Largest Contentful Paint (LCP), приоритетность LCP, а также об использовании CDN для оптимизации документов и элементов TTFB. В этой части предлагаю ознакомиться с не менее важными вещами в Core Web Vitals. И начнём мы с Cumulative Layout Shift (CLS).
Cumulative Layout Shift (CLS)
Следующий набор рекомендаций относится к Cumulative Layout Shift (CLS), которое является мерой визуальной стабильности на веб-страницах. Хотя CLS значительно улучшилась в Интернете с 2020 года, около четверти веб-сайтов по-прежнему не соответствуют рекомендуемому порогу, поэтому для них осталось немало возможностей улучшить их взаимодействие с пользователем. Первое и самое важное из них - это установить явные размеры для любого контента, загружаемого со страницы.
Layout shifts (сдвиг макета) обычно происходит тогда, когда существующий контент перемещается после завершения загрузки другого контента. Таким образом, основной способ улучшить это — зарезервировать любое необходимое пространство заранее, насколько это возможно.
Самый простой способ исправить смещения макета, вызванные неразмерными изображениями, — это явно установить атрибуты ширины и высоты (или эквивалентные свойства CSS). Однако, согласно HTTP Archive, 72% страниц имеют хотя бы одно изображение без размера. Без явного размера браузеры изначально устанавливают высоту по умолчанию 0 пикселей и могут вызвать заметное смещение макета, когда изображение, наконец, загрузится и размеры будут обнаружены.
Также важно помнить, что изображения — не единственные факторы, влияющие на CLS. Сдвиг макета может быть вызван другим содержимым, которое обычно загружается после первоначального отображения страницы, включая стороннюю рекламу или встроенные видео. Свойство соотношения сторон может помочь в борьбе с этим. Это относительно новая функция CSS, которая позволяет разработчикам явно указывать соотношение сторон для изображений, а также для элементов, не являющихся изображениями. Это позволит вам установить динамическую ширину (например, в зависимости от размера экрана), и браузер автоматически рассчитает соответствующую высоту почти так же, как это делается для изображений с размерами.
Иногда невозможно узнать точный размер динамического содержимого, поскольку оно по своей природе является динамическим. Однако даже если вы не знаете точный размер, вы все равно можете предпринять шаги, чтобы максимально уменьшить изменения макета. Установка разумной минимальной высоты почти всегда лучше, чем позволить браузеру использовать высоту по умолчанию 0px для пустого элемента. В случае если высота элемента окажется меньше, чем заданный min-height, то такой контейнер просто немного растянется.
Убедитесь, что страницы подходят для bfcache
Браузеры используют механизм навигации, называемый back/forward cache или для краткости bfcache. Он используется для мгновенной загрузки страницы из более ранней или поздней истории браузера (memory snapshot).
Bfcache — это значительная оптимизация производительности на уровне браузера, и он полностью устраняет сдвиги макета во время загрузки страницы, что для многих сайтов является уязвимостью, где происходит большая часть их ошибок CLS. Внедрение bfcache было самым большим улучшением CLS.
Несмотря на это, значительное количество веб-сайтов не имеют права на bfcache и поэтому упускают этот бесплатный буст в веб-производительности.
Владельцы сайтов должны убедиться, что их страницы могут использовать bfcache, и устранить все причины, по которым это не так. У Chrome уже есть тестер bfcache в DevTools, и в этом году планируется усовершенствовать этот инструмент с помощью Lighthouse.
Несмотря на то, что bfcache включён в раздел CLS, он также улучшит и другие основные показатели.
Избегайте animations/transitions в CSS
Еще одна распространенная проблема смещения макета — анимация элементов. Например, баннеры с файлами cookie или другие баннеры с уведомлениями, которые выдвигаются сверху или снизу, часто способствуют плохим показателям CLS. Это особенно проблематично, когда эти баннеры вытесняют другой контент, но даже если это не так, их анимация все равно может повлиять на CLS.
Страницы, использующие CSS анимацию, как правило, имеют более низкий показатель CLS. Это неудивительно, ведь каждое действие при выполнении transition или при воспроизведении какой-либо анимации приводит к сдвигу макета.
Что может удивить некоторых разработчиков, так это то, что так происходит даже в тех случаях, когда элемент вынесен за пределы обычного потока документов. Например, абсолютно позиционированные элементы, которые анимируются вверху или слева, вызовут сдвиг макета, даже если они не перемещают другое содержимое. Однако если вместо анимации сверху или слева вы анимируете transform:translateX() или transform:translateY(), это не заставит браузер обновить макет страницы и, следовательно, не произведет никаких сдвигов макета.
Предпочтение CSS анимаций, которые могут быть обновлены в потоке компоновщика браузера, уже давно является лучшей практикой с точки зрения производительности, поскольку они перемещают эту работу на графический процессор, а не в основной поток. И помимо того, что это является общей практикой, она также может помочь улучшить показатели CLS.
Подводя итог, никогда не используйте transition и анимации в CSS, требующее от браузера обновления макета страницы, за исключением случаев, когда вы делаете это в ответ на касание пользователя или нажатие клавиши (но, не при наведении курсора).
First Input Delay (FID)
Наш последний набор рекомендаций относится к First Input Delay (FID), который является мерой отклика страницы на взаимодействие с пользователем.
Новая метрика Interaction to Next Paint (INP) является возможным преемником FID, и все приведенные ниже рекомендации в равной степени применимы как к FID, так и к INP. Учитывая, что сайты хуже работают с INP, чем с FID (особенно на мобильных устройствах), мы рекомендуем разработчикам рассмотреть эти рекомендации по быстродействию, несмотря на «хороший» FID.
Избегайте или прерывайте длительные задачи
Задачи — это любая часть дискретной работы, которую выполняет браузер. Задачи включают рендеринг, компоновку, синтаксический анализ, а также компиляцию и выполнение скриптов. Когда задачи становятся длительными, то есть 50 миллисекунд или дольше, они блокируют возможность основного потока быстро реагировать на вводимые пользователем данные.
Судя по веб-альманаху есть много свидетельств того, что разработчики могли бы делать больше, чтобы избегать или разбивать длительные задачи. Разбиение длинных задач может быть не таким легким кейсом, как другие рекомендации в этой статье.
Не смотря на то, что вы всегда должны стремиться выполнять как можно меньше работы в JavaScript, вы можете немного помочь основному потоку, разбивая длинные задачи на более мелкие. Этого можно добиться, часто уступая место основному потоку, чтобы обновления рендеринга и другие взаимодействия с пользователем могли происходить быстрее.
Другой вариант — рассмотреть возможность использования таких API, как isInputPending и Scheduler API.
isInputPending — это функция, которая возвращает логическое значение, указывающее, ожидается ли пользовательский ввод. Если он возвращает true, вы можете уступить основному потоку, чтобы он мог обработать ожидающийся пользовательский ввод.
Scheduler API — это более продвинутый подход, который позволяет планировать работу на основе системы приоритетов, учитывающей, является ли выполняемая работа видимой для пользователя или же фоновой.
Разбивая большие задачи на более мелкие, вы даете браузеру больше возможностей для выполнения критически важной работы, видимой пользователю, например, обработки взаимодействий и любых связанных с этим обновлений рендеринга.
Избегайте ненужного JavaScript
В этом нет никаких сомнений: веб-сайты используют больше JavaScript, чем когда-либо прежде, и не похоже, что эта тенденция изменится в ближайшее время. Когда вы отправляете слишком много JavaScript, вы создаете среду, в которой задачи конкурируют за внимание основного потока. Это определенно может повлиять на скорость отклика вашего веб-сайта, особенно в критический период запуска.
Однако это разрешимая проблема. У вас есть несколько вариантов:
Используйте coverage tool в Chrome DevTools, чтобы найти неиспользуемый код в ресурсах вашего веб-сайта. Уменьшая размер ресурсов, необходимых при запуске, вы можете гарантировать, что ваш веб-сайт будет тратить меньше времени на синтаксический анализ и компиляцию кода, что приведет к более плавному первоначальному взаимодействию с пользователем.
Иногда неиспользуемый код, который вы находите с помощью инструмента покрытия, помечается как «неиспользуемый», потому что он не был выполнен во время запуска, но все еще необходим для некоторых функций в будущем. Это код, который вы можете переместить в отдельный пакет с помощью разделения кода.
Если вы используете tag manager, обязательно периодически проверяйте свои теги, чтобы убедиться, что они оптимизированы или используются вовсе. Старые теги с неиспользуемым кодом можно удалить, чтобы сделать JavaScript вашего диспетчера тегов меньше и эффективнее.
Избегайте больших обновлений при рендеринге
JavaScript — не единственное, что может повлиять на скорость отклика вашего сайта. Рендеринг сам по себе может быть дорогостоящей работой, и когда происходят большие обновления рендеринга, они могут мешать способности вашего веб-сайта реагировать на действия пользователя.
Оптимизация рендеринга — непростой процесс, и часто он зависит от того, чего вы пытаетесь достичь. Тем не менее, есть некоторые вещи, которые вы можете сделать, чтобы ваш рендеринг был разумным и не растягивался на длинные задачи:
Избегайте использования requestAnimationFrame() для выполнения любой невизуальной работы. Вызовы requestAnimationFrame() обрабатываются на этапе рендеринга цикла событий, и когда на этом этапе выполняется слишком много работы, обновления рендеринга могут задерживаться. Очень важно, чтобы любая работа, которую вы выполняете с помощью requestAnimationFrame(), была зарезервирована строго для задач, связанных с отрисовкой обновлений.
Держите размер DOM небольшим. Размер DOM и интенсивность работы по верстке плотно взаимодействуют. Когда средству визуализации необходимо обновить макет для очень большого DOM, работа, необходимая для пересчета его макета, может значительно увеличиться.
Используйте CSS containtment. CSS containtment зависит от свойства CSS contain, которое дает браузеру инструкции о том, как выполнять работу с макетом для контейнера, для которого установлено свойство contain, включая даже изоляцию области макета и рендеринга в определенный корень в DOM. Это не всегда простой процесс, но, изолируя области, содержащие сложные макеты, вы можете избежать ненужной работы по макетированию и рендерингу.
Заключение
Улучшение производительности страницы может показаться сложной задачей, особенно с учетом того, что в Интернете существует множество руководств, которые необходимо учитывать. Однако, сосредоточившись на этих рекомендациях, вы сможете подойти к проблеме сфокусированно и целеустремленно и, надеюсь, улучшите результаты основных показателей вашего веб-сайта.
Хотя приведенные здесь рекомендации ни в коем случае не являются всем пулом рекомендаций, считается, что эти они являются наиболее эффективными, с помощью которых сайты могут повысить производительность основных показателей в 2023 году.
Если вы хотите выйти за рамки рекомендаций, перечисленных здесь, ознакомьтесь с этими руководствами по оптимизации для получения дополнительной информации:
Пусть ваши сайты будут быстрыми для ваших пользователей во всех наиболее важных аспектах.