Как оптимизировать скорость сайта

Изменения в Google PageSpeed

В конце 2018 старый механизм PageSpeed заменили оценками и аналитикой Lighthouse. И этот новый инструмент также встроен в Google Chrome. Основное отличие от предыдущих версий — баллы, которые теперь присуждаются не только за выполнение рекомендаций, но и непосредственно за скорость. Загрузка страницы начала оцениваться по нескольким временным параметрам:

  • в какой момент времени после начала загрузки становится виден контент;
  • когда можно взаимодействовать со страницей — кликать или вводить данные;
  • насколько медленно это все грузится, и когда все операции будут завершены.

Вот как написано на официальном сайте:

«На результат измерения скорости загрузки в разной степени влияет множество факторов. Основные из них — это доступность локальной сети, доступность аппаратных средств клиента и наличие конфликтов при доступе к ресурсам клиента.»

На самом деле, повлиять может все что угодно, поэтому для более релевантной оценки, рекомендуется сделать не 1 замер, а 3-5 в течение дня в разное время суток.

В 2020-ом произошло обновление движка Lighthouse 6, на базе которого работает PageSpeed Insights. В Lighthouse 6 разработчиками было добавлено несколько значительных изменений. Появились новые метрики, которые ощутимо влияют на общую оценку быстродействия страницы. Обновились аудиты для «доступности» и Javascript.

Ключевые метрики:

  • Largest ContentFul Paint (LCP) — отрисовка крупного контента. Время, за которое большая часть контента отрисовывается на экране. Желательное время до 2,5 секунд, приемлемое — до 4 секунд.
  • First Input Delay (FID) — задержка между первым действием пользователя и реакцией браузера. Желательное время до 100 мс, приемлемое — до 300 мс.
  • Cumulative Layout Shift (CLS) — совокупный сдвиг макета. Показывает оценку визуальной стабильности страницы. Нацелено на борьбу с всплывающей рекламой и блоками, которые появляются и пропадают без действий со стороны пользователя. Если изображение «скачет», топоказатели падают. Нормальное значение до 0,1, допустимое — до 0,25.

И вот эти показатели из отчета входят в Core Web Vitals. А значит, метрики будут существенно влиять на ранжирование поисковой выдачи. Важное условие — как минимум 75% страниц сайта должны соответствовать нижним границам этих трёх показателей. Иначе сайт будет признан Google плохо оптимизированным. Но при этом сами показатели имеют разные веса в учете суммарной оценки, например, LCP или FID влияют на итоговую сильнее, чем CLS.

В ноябре 2020 года Google подтвердил, что Core Web Vitals станет фактором ранжирования с мая 2021 года. Рекомендации как и раньше есть, но теперь они напрямую не связаны с баллами. Совершенно не факт, что следование рекомендациям улучшит ситуацию, так как выполнение некоторых из них может ухудшить ситуацию или быть неприемлемым с точки зрения поддержки различными браузерами. Ранее частенько встречалась ситуация, когда очевидно тормозящие сайты выдавали отличные оценки, а быстрые сайты оценивались плохо. Теперь с изменением алгоритмов становятся важными именно скорость и восприятие пользователем. Все маркетинговые погремушки, которые так любят запихнуть на первый экран, теперь неизбежно будут ухудшать оценку, как ты их не отлаживай. Поэтому рекомендация на будущее: на странице, особенно на первом экране, должен быть только максимально необходимый контент, желательно с минимумом анимаций и сторонних включений.

Как улучшить производительность?

Широко рекомендуется использовать асинхронную загрузку. При этом следует помнить, что асинхронный и «не влияющий на скорость загрузки» — разные вещи. Да, он позволяет загружать ресурсы параллельно, не блокируя какой-то из них, но общее время все равно увеличивается. Далее, если код вы уже вынесли вниз страницы, то добавление асинхронности ничего в плане блокирования загрузки контента не изменит. Так что асинхронность не панацея, а лишь способ частично улучшить ситуацию. Намного эффективнее — это использовать как можно меньше кода в целом, например, загружать не всю библиотеку, а только те компоненты, которые вам необходимы конкретно на этой странице.

Отсюда вытекает, что билд лучше дробить на составные части, дабы в дальнейшем мы могли подключать и задействовать только те вещи, которые нужны только на этой странице, более того, даже такой код лучше разбить на 2 части. Первая — это «критические» вещи, отвечающие за каркас вашего приложения и наполнение первого экрана. Вставляем их прямо в код. Все остальное ниже, а интерактив, требующий действий пользователя, вообще в конец страницы.

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

  • Можно настроить кэширование на своем сервере и обновлять по крону, но помимо банального неудобства такого решения оно может ничего и не улучшить. А вот настройка самого контейнера на загрузку сценариев по событию способно поправить ситуацию. Нас интересует, естественно, отложенная загрузка по событию. В идеале подгрузку таких вещей стоило бы отложить до полной загрузки страницы, но аналитики скорее всего будут против, так как, например, если пользователь уйдет с сайта до момента полной загрузки, они не получат вообще никакой информации. Но, как минимум, стоит ориентироваться на событие DOM Ready только для сбора наиболее критичных метрик.
  • Можно использовать service worker, он будет кешировать часть или всё содержимое HTML-страницы. Сервис обновляет кеш только при каких-либо изменениях на странице.
  • Указывайте размеры изображений и видео в тэгах, это опять полезно. Если изображения адаптивные, указывайте хотя бы пропорции (например, 16:9).

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

 Во-первых, для видео, которое не нужно автоматически прокручивать, используйте атрибут preload=»none». Для видео, которое используется в качестве анимаций, указывайте атрибут poster=»» и используйте код JavaScript, аналогичный примерам отложенной загрузки изображений на основе Intersection Observer.

Некоторые необязательные вещи можно вообще вынести со страницы, подтягивать их только после действий пользователя. Это также относится и к скриптам, выполняющим специфические задачи, вроде: обращения к сторонним ресурсам, перестроения графиков данных или капчи. Это позволит нам не грузить лишние строки, а также уберет пункты из показателя «неиспользуемый код».

Можно применить web-workers — специальное API-решение, позволяющее загружать JavaScript, который не связан с пользовательским интерфейсом в фоновом режиме. Можно отказаться от отрисовки тяжелого содержимого в браузере в пользу серверного рендеринга. Так вы сократите время ответа сервера. Держите проект на быстром хостинге или VPS/VDS, мониторьте потребление ресурсов, оптимизируйте базу данных, настройте кеширование. Перейдите на новую версию PHP. Версия 7.3 работает в 3-4 раза быстрее старых редакций.

Используйте протокол http/2, он позволяет быстрее и эффективнее передавать данные между браузером и сервером. В отличие от http/1 он не создает отдельные соединение для загрузки каждого файла, а загружает их параллельно. Таким образом, http/2 уменьшает нагрузку на сервер и экономит его ресурсы.

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

Что касается предпочтительности той или иной анимации, то все упирается в качество изображения и продолжительность. В силу наиболее продвинутых алгоритмов сжатия, видео предпочтительнее использования секвенции. Кроме того, в самом видео предпочтительно использовать новый формат WebM, поскольку он специально разработан для потоковой передачи через интернет. WebM намного меньше по сравнению с MP4. А такие решения как гиф-анимация вообще вызывают предупреждение PageSpeed с просьбой использовать более современные форматы. Выбор же между WebGL или видео для анимаций уже сильно неоднозначен, предсказать результат заранее не получится. В целом следует исходить из соотношения веса решений к их продолжительности.

Также иногда возникает вопрос: на некоторых сайтах сперва изображения не очень четкие, а потом они прогружаются, это же ускорение работы сайта? Визуально — да, но по факту — нет. Для подобной технологии мы сперва вынуждены грузить маленькие по весу изображения, а потом асинхронно подтягивать качественные. Это не частичная загрузка большого файла «побыстрей», а дополнительная предзагрузка маленького. Для пользователя это неплохо, а вот метрики таким не улучшить.

Не забываем про шрифты, помимо использования подходящих форматов, рекомендуется использовать rel=»preload» как и для скриптов.

Также в стилях стоит указать font-display:swap; — это даст возможность использовать встроенные шрифты в ожидании загрузки основного.

Частым кейсом проблем со смещением макета, не связанным с всплывающей рекламой, являются слайдеры и плавающие сайдбары. В первом случае проблема связана с тем, что в странице создана только обертка слайдера, а все внутренности и размеры задаются уже после инициализации скрипта, что вызывает изменение размеров и пересчет координат всей страницы, поэтому не забывайте заранее указывать в стилях размеры нужного блока. А для плавающих сайдбаров вместо изменения значений с помощью скриптов лучше используйте свойство position: sticky.