Инструменты для анализа производительности сайта
- четверг, 6 марта 2025 г. в 00:00:09
В этой статье речь пойдет об инструментах, с помощью которых можно проанализировать качество спроектированного front-end разработчиком сайта. В качестве наглядного материала используется проект, реализованный на базе Next.js 14-й версии с app router.
Во время создания высоконагруженного приложения каждый front-end разработчик сталкивается с задачей оптимизации кода в проекте. Одним из инструментов, которые помогут найти проблемные места, является вкладка performance в DevTools. Этот инструмент позволяет составить отчет о действиях пользователя на сайте. С помощью отчета разработчик может получить подробную хронологическую информацию о загрузке страницы:
функции, которые вызывались в течении записи отчета;
информацию о расходе памяти;
блок со скриншотами экрана, где можно наглядно увидеть, что будет отображено для пользователя в конкретный момент времени.
Рассмотрим более детальнее каждый блок на рис. 1. В верхней части отчета можно увидеть, как нагружался наш CPU во время загрузки страницы (красный блок). Затем идет блок со скриншотами экрана, на которых показано, что видит пользователь во время загрузки контента страницы (синий блок). Далее идет самый важный блок этой вкладки – это блок Main с подробной информацией о том, какие функции вызвались, какие события их инициировали (черный блок). Также в этом отчете содержится информация о нескольких показателях (оранжевый блок), по которым мы можем судить о скорости и производительности сайта:
First Paint (FP) – отражает время, когда пользователь увидит первое изменение содержимого страницы на своем экране (например, фон поменяет цвет);
First Content Paint (FCP) – очень похож на предыдущий, но с одним отличием: он показывает время, когда на экране появляется первый смысловой контент (изображение, текст);
Largest Contentful Paint (LCP) – этот показатель дает понять сколько понадобилось времени для отрисовки самого большого блока на этой странице (как правило это картинки, но может быть и просто блок с большим количеством текста);
DOMContentLoaded (DCL) – это событие триггерится после того как HTML был загружен и разобран в DOM дерево элементов, при этом сторонние ресурсы (например, скрипты или картинки) могут быть еще не загружены;
OnLoad (L) – завершающее событие при загрузке страницы сайта, отражает время, когда загружены все элементы страницы.
Перейдем к анализу блока Main. В нем содержится информация об основном потоке нашего приложения, о том какие функции были вызваны, сколько понадобилось времени на их выполнение и какие изменения последовали после обработки этих функций.
Для примера рассмотрим один из блоков.
На рис. 2 видно, как загружается компонент DeliveryPopup, а также все его внутренние составные части. С помощью фильтров можно найти те компоненты, которые загружаются при первоначальном рендеринге. Анализируя результаты загрузки страницы, можно понять, какие компоненты лучше исключить при первоначальном открытии. В некоторых ситуациях может быть затрачено много времени на загрузку и обработку таких компонентов, т.к. они могут содержать много логики, запросов к бэкенду и т.д.
Если разработчик понимает, что при первом рендеринге компонент ему не нужен (например, модальные окна или компоненты, которые зависят от действий или выбора пользователя), то их загрузку можно отложить с помощью отложенного импорта (dynamic import).
Сформируем еще один отчет, после того как импортировали DeliveryPopup динамическим способом.
Как видно из рис. 3, компонент больше не загружается при первоначальной загрузке страницы. Таким образом, разработчик сможет максимально облегчить свою страницу при первом открытии и оставить только необходимые компоненты.
Отложенная загрузка компонентов будет влиять на показатели FC и FCP в первую очередь, т.к. мы облегчаем изначальный размер нашей страницы.
Также на FC и FCP положительно влияет серверный рендеринг в сочетании с компонентами loading (особенности next.js app router). В этом случае, пока выполняется запрос на сервере, пользователь уже видит часть контента (как правило, в таких случаях отображают скелетоны или лоадеры). Тем самым мы улучшаем показатели FC и FCP. К плюсам серверного рендеринга можно отнести следующее: при проблемах с сетью на стороне пользователя, человек будет ждать появление контента меньше по времени, чем он бы ждал при использовании клиентских запросов (это время будет складываться из времени для запроса страницы + времени обработки запросов на сервере, что будет существенно меньше, чем на клиенте).
Рассмотрим несколько примеров работы с запросами. Будем проводить анализ на странице со списком заказов. Для сравнения используем обычную скорость сети и имитацию fast 4G. Первая ситуация – это серверный запрос данных.
Для удобства составлена таблица с результатами:
| Без задержек сети | Fast 4G |
FC, мс | 960 | 1340 |
Отображение результатов запроса, мс | 1400 | 2950 |
В текущей реализации использовался префетч запроса на сервере в связке с loading-компонентом, что позволило серверу отдать маленькую страницу заглушку и ждать ответа на запрос. Как только был получен ответ на сервере, скелетон сменился на контент (результат запроса). Именно это время указано в таблице во второй строке, т. е. когда пользователь увидел запрашиваемые данные. Первая строка (FC) – это показатель, когда пользователю начал отображаться скелетон нашей страницы.
Перейдем к сравнению с клиентским запросом данных.
По результатам тестирования составлена такая же таблица, как и в случае с серверным запросом.
| Без задержек сети | Fast 4G |
FC, мс | 1390 | 1940 |
Отображение результатов запроса, мс | 3750 | 8800 |
Как видно из таблицы, все показатели ухудшились. Перестала отдаваться маленькая страница loading, которая позволяла достичь хороших показателей FC и FCP. Также увеличилось время, за которое пользователю отображались реальные данные, а не заглушка. Чем больше будет ухудшаться скорость сети, тем больше будет заметна разница между префетчем данных на сервере и запросом на клиенте.
Получается, что во всех случаях клиентский запрос «проиграл» серверному. Следовательно, можно сделать вывод о необходимости префетча данных на стороне сервера в связке с компонентом loading. Такой вариант не подойдет только в одном случае, когда нам важно отдать готовую страницу с данными с сервера (пропуская этап скелетона-заглушки). Это важно для страниц, которые индексируются роботами и нужно отдавать сразу готовый результат (например, главная). В случаях, где SEO нам не так важно, предпочтительней использовать серверные запросы в сочетании с loading-страницей.
Существует ряд ситуаций, в которых показатели FC, FCP и т.д. могут падать. В некоторых случаях это происходит при использовании неоптимальной архитектуры проекта со стороны front-end части. Ряд причин ухудшения показателей:
большое количество серверных запросов – не стоит злоупотреблять серверным рендерингом, если разработчик будет делать абсолютно все запросы с сервера, то это сильно повысит нагрузку на него и увеличит время ожидания страницы при первой загрузке;
неоптимизированный код – многочисленное дублирование, неиспользование ленивой загрузки как для компонентов, так и для изображений, будет негативно сказываться на времени загрузки страницы;
неверный формат и размер изображений – это довольно частая ошибка, когда в маленький контейнер помещают картинку в разы превышающую его размер. Чтобы избежать этого, можно использовать imgproxy, с помощью которого можно преобразовать картинку к формату webp, а также уменьшить ее до нужного размера. Таким образом, снижается нагрузка на сеть.
Вкладка Performance дает возможность подробно узнать о том, что происходит на странице в разные моменты ее работы. Также с помощью нее можно отследить многие важные показатели, найти проблемные места, из-за которых ваш сайт медленно работает.
В рамках обзора средств для анализа производительности сайтов выйдут вторая и третья части.
Благодарю за внимание!