Ключевые метрики для определения целей оптимизации
Для того чтобы что-то оптимизировать, нужно понять, что требует улучшения, по каким метрикам это можно увидеть и текущее их состояние.
Компания Google создала группу метрик, которую назвала Web Vitals. Они считаются жизненно важными для каждого приложения. На текущий момент их всего три: Interaction for Next Paint (INP), Cumulative Layout Shift (CLS) и Largest Contentful Paint (LCP). Давайте рассмотрим каждую метрику подробнее.
Interaction for Next Paint — это метрика, которая показывает, насколько быстро ваше приложение реагирует на действие пользователя. INP отслеживает задержки всех взаимодействий со страницей: щелчков кнопки мыши, касаний пальцем по экрану и нажатия кнопок на клавиатуре. Простыми словами, эта метрика про отзывчивость приложения. Хорошая отзывчивость означает, что страница быстро реагирует на взаимодействие приложения и пользователя. Отличным результатом считается отзывчивость до 200 миллисекунд, от 200 до 400 — ситуация требует улучшения, а всё, что больше, — это уже плохо и требует скорейшей оптимизации.
Cumulative Layout Shift показывает совокупный сдвиг элементов на странице относительно своего первоначального элемента. Представьте, что вы зашли на сайт, он еще не до конца загрузился, но вы уже знаете, куда вам нужно нажать, поскольку элемент уже отрисовался. Вы наводите мышь, жмете левую кнопку — и прямо в этот момент сверху появляется баннер с рекламой, что сдвигает нужный элемент вниз, и вы кликаете на рекламу. Знакомо? Это и есть тот самый сдвиг. Значение этих метрик измеряется формулой, в результате которой получается число. Хороший показатель — 0,1 и ниже, от 0,1 до 0,25 — это хуже ожидаемого, больше — нужны положительные изменения.
Largest Contentful Paint — ключевая метрика, если мы рассматриваем загрузку приложения и доставку контента до пользователя. Она показывает, насколько быстро пользователь получает контент, — чаще всего это картинки, видео и блоки с текстом. Все возможные значения попадают в следующие зоны:
- Зеленая — от 0 до 2,5 секунды. Приложение загружается достаточно быстро, пользователи довольны.
- Желтая — от 2,5 до 4 секунд. Приложение загружается медленнее, чем должно. Пользователи замечают, что загрузка долгая, и уровень удовольствия падает. Нужно исправлять ситуацию.
- Красная — больше 4 секунд. Большинство пользователей просто не дождется загрузки приложения и будет использовать альтернативные варианты.
Отмечу, что эти значения относятся к 75-му процентилю пользователей. Это значит, что у большинства пользователей ваше приложение в идеале должно попадать в зеленую зону по каждой метрике. Значения одинаковы как для мобильных, так и для десктопных девайсов.
Определившись с метриками, я стал смотреть на архитектуру приложения и технологии, применяемые в нем: какой фреймворк и библиотеки используются, как разбит код, как происходит загрузка ресурсов (скрипты, стили, общение с сервером и т. д.). Разберем каждый аспект по пунктам.
Фреймворк и аудит
Современные веб-приложения написаны с использованием фреймворков. Поэтому мне не нужно было беспокоиться о сжатии кода и о его сборке — всё это работало из коробки.
Дальше я провел аудит приложения на предмет использования библиотек. Возможно, что часть из них была слишком тяжеловесной и было бы рационально от нее отказаться. Что-то из зависимостей оказалось не таким сложным в разработке, поэтому я написал свое решение вместо скачивания библиотек. А какие-то и вовсе устарели и больше не используются приложением — их просто забыли убрать в круговороте разработки.
Хороший пример — замена Moment.js на Day.js. Это библиотеки для работы с датой, и Day.js является альтернативой Moment.js с тем же API, но только весом в 2 КБ. Это помогло уменьшить размеры приложения и ускорить его скачивание клиентом.
Подход «ленивой загрузки»
Очень часто пользователю не нужно всё веб-приложение целиком и сразу. Клиент заходит на какую-то страницу приложения и просматривает ее. Соответственно, нет смысла включать в загрузку этой страницы код для десятка других, которые, возможно, человек даже не посетит. Можно подгрузить необходимый код в тот момент, когда пользователю он понадобится.
Поэтому для оптимизации веб-приложения я применил так называемый подход «ленивой загрузки». Смысл подхода заключался в том, чтобы отдать пользователю только самое необходимое в текущий момент. Остальное либо загрузить в фоне (что никак не скажется на времени загрузки контента основной страницы), либо тогда, когда клиент воспользуется, например, навигацией на другую страницу.
Применение этого подхода на проекте позволило существенно уменьшить размер необходимого кода для первоначальной загрузки приложения, что положительно сказалось на скорости его загрузки.
Оптимизация загрузки ресурсов
Ресурс — это любой скрипт, объект, запрос на сервер, необходимый для работы приложения. Для того чтобы браузер быстро обработал код и быстрее отрендерил элементы, я выполнил несколько шагов:
- Уменьшил количество HTML. Чем больше элементов, тем больше времени нужно на построение DOM-дерева.
- Уменьшил количество CSS. Загрузил только те стили, которые действительно нужны. Чем больше стилей, тем больше времени понадобится на построение CSS-дерева.
- Правильно загрузил скрипты с помощью атрибутов async/defer. Когда браузер видит тег script при обработке HTML, он останавливает дальнейшую обработку верстки, скачивает и выполняет скрипт. И пока браузер не закончит со скриптом, парсинг HTML не продолжится. Атрибуты async/defer меняют это поведение и позволяют загружать скрипты в фоне, не блокируя парсинг верстки.
Только после этих трех пунктов на клиенте начинают появляться первые элементы. Поэтому критически важно их оптимизировать.
Еще несколько советов, которые помогут ускорить приложение
Важные запросы должны выполняться как можно раньше. Если обработка запроса зависит от скриптов, которые еще не загружены клиентом, то делайте запрос на сервер и загружайте скрипты в параллели. Это позволит быстрее начать обработку ответа.
Используйте font-swap. Если в приложении используются шрифты, которых нет по умолчанию в браузере, то примените swap при подключении шрифтов. Это позволяет показывать текст со шрифтом по умолчанию, пока основной шрифт еще не загружен. Пользователь будет видеть текст раньше.
Используйте кеширование. Это позволит клиенту реже скачивать ресурсы, соответственно, это положительно повлияет на конечную скорость отрисовки страницы, так как мы исключаем поход по сети.
Результаты
После проведенных оптимизаций я получил внушительные результаты. Размер загружаемого приложения сократился с 7 до 1,4 МБ, а время Largest Contentful Paint (LCP) сократилось с 3,3 до 1,9 секунды. Это означает, что пользователи теперь быстрее получают доступ к полезному контенту, что в свою очередь повышает удовлетворенность пользователей от использования продукта. Эти изменения позволяют приложению уверенно оставаться в зеленой зоне Web Vitals и продолжать радовать своих пользователей быстрой и эффективной работой.
Эти примеры оптимизации не только улучшили производительность конкретного приложения, но и демонстрируют важность постоянной заботы об оптимизации веб-приложений. Оптимизация загрузки — это непрерывный процесс, требующий внимания и усилий, но результаты, как видно из этого примера, могут быть впечатляющими. В конечном итоге это улучшает не только пользовательский опыт, но и успех бизнеса в целом.