Некоторые приложения загружаются быстро, некоторые медленно, но почему? Является ли скорость загрузки страницы единственным показателем производительности приложения?

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

Когда начинаются проблемы с производительностью

Вы можете разрабатывать веб-приложения годами и почти не сталкиваться с проблемами производительности приложений.

Но, скорее всего, проблемы возникают в следующих ситуациях:

  1. Появляются большие данные (нужно отображать большие списки или сотни тысяч точек на карте).
  2. Приложение становится большим (сотни кастомных скриптов, десятки экранов, форм и т. Д.).
  3. Большое количество клиентов из разных регионов (например, 300 000+ клиентов в день со всего мира).
  4. Высокая конкуренция на рынке (наверняка пользователь предпочтет приложение вашего конкурента, если оно будет работать быстрее).
  5. Вам нужна мобильная версия (браузеры на мобильных устройствах по-прежнему страдают от проблем с производительностью).

Из чего состоит спектакль

В глобальном масштабе проблемы производительности веб-приложений можно разделить на две категории: передача данных и время выполнения.

  • Под передачей данных мы подразумеваем загрузку любых ресурсов, необходимых для работы приложения.
  • Под runtime - работа приложения, рендеринг и обработка пользовательского ввода.

Каждая из этих категорий содержит множество нюансов, о которых мы часто не задумываемся, но которые отличают качественные приложения от некачественных.

Это самые популярные показатели производительности веб-приложений (все они должны быть минимальными):

Загрузка страницы

  • TTFB - время до первого байта.
  • FCP - Первая содержательная краска.
  • FMP - Время первой осмысленной краски.
  • TTI - Time To Interactive (время, пока страница не сможет отреагировать на ввод пользователя).

Время выполнения

  • Время отклика на ввод пользователя.
  • Время перерисовки интерфейса.

Хотя TTFB и TTI являются показателями производительности загрузки страницы, на них могут влиять проблемы, связанные со средой выполнения.

Как искать и анализировать проблемы с производительностью

Основной набор инструментов в арсенале разработчика - Chrome DevTools или аналогичные инструменты, такие как Инструменты разработчика Firebug / Firefox.

Сеть - позволяет детально проанализировать, какие ресурсы загружаются на страницу, с каких ресурсов, с какой скоростью и так далее. Этот инструмент часто используется для ручного анализа скорости загрузки страницы.

Производительность - на этой вкладке можно включить запись вызовов выполнения кода, операций ввода-вывода и прочего. Кроме того, запись может быть сделана с эмуляцией регулирования сети и ЦП. Например, вы можете проверить производительность приложения на слабых устройствах.

Маяк - встроенный в Chrome DevTools инструмент, который запускает загрузку страниц, записывает метрики, анализирует их и даже дает рекомендации по повышению производительности.

Как измерять и контролировать производительность

Инструменты мониторинга производительности веб-приложений можно разделить на две категории: те, которые выполняют синтетические измерения, и те, которые записывают данные о производительности от реальных пользователей.

  • К синтетическим инструментам мониторинга относятся Lighthouse и Webpagetest.
  • Для реального мониторинга пользователей (RUM - real user monitoring) подойдут mPulse и Sematext.

Кроме того, существуют такие инструменты, как Webpack-bundle-analyzer, которые нельзя отнести к этим двум категориям. Но с их помощью можно измерить некоторые параметры, которые влияют на производительность, например размер бандла.

Передача данных

TCP-соединение, DNS-поиск - вы можете ускорить загрузку страницы, даже правильно настроив серверные соединения. В частности, если вы используете предварительную выборку DNS или даже IP-адреса вместо доменных имен.

TTFB (время до первого байта). Время до первого байта - важный показатель. Чтобы ускорить его, вы должны попытаться реализовать как можно меньше логики на сервере перед выдачей index.html.

HTTP1 vs HTTP2 - HTTP2 может значительно ускорить загрузку страницы за счет мультиплексирования или сжатия заголовков. Кроме того, новый (относительно) протокол открывает массу возможностей, например, server push.

Шардинг домена. Если вам нужно передать много HTTP-заголовков для запросов API, но не для статических запросов, лучше разделить их по разным доменам.

CDN (Content Delivery Network) поможет ускорить загрузку для географически распределенных клиентов.

Приоритизация ресурсов (предварительная загрузка, предварительная выборка, предварительное подключение) - это ускорение загрузки страницы за счет правильной стратегии загрузки ресурсов. Браузеры позволяют устанавливать приоритеты для разных типов ресурсов и загружать раньше, что важно для первого рендеринга.

Статическое сжатие: GZIP и Бротли. Brotli - это алгоритм сжатия, который уменьшит вес статики и, таким образом, увеличит скорость загрузки. И вот отличное решение от моего коллеги.

Webp vs Png & Jpg. Webp - отличная альтернатива Png. Помимо меньшего веса изображений, Webp не уступает по качеству. Сейчас этот формат поддерживает около 78% браузеров. Но даже если вам нужна 100% поддержка, вы можете реализовать обратный ход на Png, используя изображение тега.

Время выполнения

Задачи, Микрозадачи. При правильной расстановке приоритетов при развертывании кода вы можете избавиться от фризов и ускорить реакцию на ввод данных пользователем.

RequestIdleCallback - полезная функция, которая позволяет развернуть код в свободное время в конце кадра (кадр / тик) или когда пользователь неактивен. Поможет избавиться от все тех же лагов и фризов.

RequestAnimationFrame позволяет вам правильно планировать анимацию и максимизировать ваши шансы на рендеринг 60 кадров в секунду.

ES2015 vs ES5. ES2015 предоставляет множество функций, более мощных, чем ES5.

Манипуляция DOM. Манипуляции с DOM дороги и должны выполняться осторожно и разумно. Например, не вызывайте querySelector () в цикле, если вы можете сделать это одним вызовом.

Рендер блокирующий ресурс. Загрузка некоторых ресурсов может заблокировать рендеринг. Чтобы этого избежать, следует использовать атрибуты defer, async, preload.

60 FPS по указателям-событиям: none - отличный прием, который можно использовать для достижения 60 FPS при прокрутке страницы. Работает это очень просто: все обработчики событий мыши отключены при прокрутке.

Пассивный слушатель событий - это способ сделать плавную прокрутку страниц на сенсорных экранах. Короче говоря, в браузере несовершенный поток обработчиков событий касания. Если вы установите пассивный параметр при создании обработчика событий, браузер четко поймет, что обработчик не отменяет прокрутку и рендеринг, не дожидаясь ее завершения.

Виртуальная прокрутка - это умный способ не отображать большие списки, а создавать их при прокрутке. Он потребляет меньше памяти и упрощает прокрутку списков.

Избегайте больших сложных макетов и разбивки макетов. Макет / перекомпоновка - дорогостоящие операции, при которых выполняется много перерасчетов параметров рендеринга. Чтобы избежать их частого вызова, вам необходимо построить макет и правильно управлять DOM.

Что заставляет layout / reflow - это шпаргалка, в которой вы можете найти список функций и параметров, которые вызываются layout / reflow.

Строительство

Встряхивание дерева - убрать с бандита неиспользуемый код и ускорить загрузку страницы.

Разделение кода - разбив код на части, можно оптимизировать первую загрузку и открыть возможность загрузки частей кода лениво.

Обфускация может уменьшить размер бандита и даже немного помочь скрыть ваш код от чужих глаз.

Архитектура

Рендеринг на стороне сервера, вероятно, самый известный способ убедиться, что SPA отображается сразу при первой загрузке. Это важное требование для некоторых поисковых систем (и не только).

Ленивая загрузка изображений и видео (+ native) - нативное решение, предназначенное для улучшения показателей первого рендеринга за счет ленивой загрузки изображений и видео.

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

Кеширование файлов с помощью сервис-воркеров позволяет кэшировать файлы в браузере и не загружать их каждый раз с сервера. Пожалуй, единственный способ сделать офлайн-режим в браузере.

HTTP-кеширование - с помощью некоторых HTTP-заголовков можно значительно повысить скорость загрузки страницы и снизить нагрузку на сервер.