Производительность - это основная часть взаимодействия с пользователем в Интернете. Когда производительность низкая, пользователи не так часто совершают конверсии.

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

Самое главное - измерить то, что действительно важно для пользователей. Я собираюсь показать вам, как анализировать и улучшать медленно работающий код JavaScript. Мы сделаем это с помощью инструментов разработчика Chrome.

Я расскажу об API браузера, которые позволяют нам отмечать и измерять наш код. Мы будем использовать небольшое демонстрационное приложение, которое мы сможем анализировать и улучшать по мере продвижения.

Предпосылки

Если вы хотите следить за демонстрацией, прочтите следующее. В противном случае пропустите этот раздел!

Вам потребуется установить следующее:

  • мерзавец
  • npm
  • редактор кода по вашему выбору

Также будет полезно иметь представление о JavaScript, React и иметь базовые знания о Chrome DevTools.

Настройка демонстрации

git clone https://github.com/richiemccoll/visualising-front-end-performance-demo.git
git checkout before-fixes
npm i
npm start

Это должно открыть для вас новое окно браузера, которое должно выглядеть примерно так:

User Timings API

Первое, что нам нужно обсудить, это как измерить медленно работающий код.

Браузеры предоставляют интерфейс в окне под названием window.performance. Мы можем использовать это для получения информации о производительности текущей страницы. В этой демонстрации мы сосредоточимся на двух методах.

window.performance.mark ()

Судя по названию, этот API позволит нам вставлять метки начала и конца в медленно работающие функции. Метка - это просто отметка времени с соответствующим именем.

Мы можем использовать это так:

window.performance.measure ()

Этот API позволит нам создать меру между двумя отметками (начало и конец). Мера также является меткой времени с соответствующим именем.

Создание этой меры поможет нам визуализировать функции в инструментах разработчика. Если вы забудете добавить это, вы ничего не увидите 👀.

Мы можем использовать это так:

Это все, что нам нужно рассказать о window.performance, но я рекомендую проверить полный API на MDN.

Анализ пользовательского интерфейса

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

Функция, которую мы будем анализировать, - это изменение порядка (самый старый - самый новый) запусков SpaceX. Если у вас есть демо-версия, попробуйте нажать кнопку, чтобы изменить порядок. Теперь откройте Chrome DevTools и перейдите на вкладку «Производительность».

Этот экран может показаться немного устрашающим, если вы с ним не знакомы. Это отличная ссылка для понимания того, как им пользоваться.

Давайте изменим параметр троттлинга процессора на 6-кратное замедление, а затем попробуем нажать эту кнопку несколько раз.

Вы замечаете что-нибудь другое? Это кажется немного вялым. Если мы нажмем кнопку записи при нажатии на эту кнопку, мы сможем увидеть, какую работу на самом деле выполняет браузер.

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

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

Получение базовой линии

Первое, что нам нужно сделать, это получить базовое измерение, отметив начальную и конечную точки. Давайте создадим начальную метку в обработчике события onClick для кнопки.

Откройте src/components/LatestLaunches.js и добавьте его перед вызовом setOrder.

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

Мы можем сохранить значение из предыдущего рендера в ссылке с помощью настраиваемого хука, называемого usePrevious.

Чтобы использовать этот настраиваемый перехватчик, нам нужно создать новый эффект, который будет запускаться после рендеринга компонента LatestLaunches. Это означает, что мы увидим, сколько работы браузер выполняет в целом.

Теперь вернитесь к Chrome DevTools, нажмите запись и снова нажмите эту кнопку!

changingOrder-measure - это наша первая базовая линия. Это число, которое мы постараемся улучшить. На моем компьютере отображается около 800 мс.

Помните: мы ввели минимальную инструментальную работу для получения измерений (настраиваемая ловушка usePrevious), поэтому мы исключили ее продолжительность из меры.

Исправьте # 1 и измерьте

Давайте сначала займемся низко висящими фруктами. Мы можем предотвратить повторную отрисовку компонента Card React слишком много раз. React предоставляет готовую утилиту под названием memo, которую мы можем использовать.

Давайте откроем src/components/Card.js и импортируем это.

Затем мы можем использовать его, передав компонент, который хотим запомнить.

Теперь давайте вернемся к DevTools, сделаем еще одну запись и посмотрим, как эти изменения повлияют на наши базовые показатели.

Новое базовое значение находится в диапазоне 600–700 мс. Это все еще не очень хорошо. Итак, какие еще исправления мы можем сделать?

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

1. Мы говорим магазину Launch обновить его внутреннее состояние заказа.

2. Затем React получает это новое значение в качестве реквизита. React запускает алгоритм согласования, чтобы обновить порядок карточек.

3. Затем браузер должен запустить Style, чтобы пересчитать стили, которые изменились для каждой карточки.

4. По мере изменения карточек браузер запускает Layout для расчета размеров и положения каждой из них.

5. Затем браузер отобразит обновление заказа на экране.

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

Давайте посмотрим, сколько элементов Card у нас в DOM.

СОВЕТ. Это можно быстро сделать, открыв вкладку "Элементы" в DevTools. Щелкните правой кнопкой мыши элемент div, содержащий карточки, и сохраните его как глобальную переменную. Доступ к свойству childElementCount сообщает нам, что в DOM 96 карточек.

С точки зрения пользовательского интерфейса в любой момент времени отображается около 5–10 карточек. Это также означает, что нам не нужно иметь 96 из них в DOM.

Виртуализация

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

Есть несколько библиотек, которые предоставляют эту технику из коробки. Вот некоторые примеры:

Я решил выбрать masonic в этой демонстрации, поскольку для начала работы требуется минимальная индивидуальная реализация.

Исправьте # 2 и измерьте

Давайте импортируем компонент Masonry в src/components/LatestLaunches.js.

Давайте изменим способ отображения списка карточек.

Пора еще немного записать и нажать кнопку. Вернемся к Chrome DevTools.

Приятно 🔥. Сейчас все становится немного лучше, когда мы сокращаем количество элементов DOM. Базовый уровень сейчас составляет около 7 0–150 мс. Использование виртуализации позволило сократить время работы на полсекунды.

Заключение

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

Ключевой вывод - понимание цикла измерения, анализа и исправления. Для решения проблем с производительностью внешнего интерфейса мы можем использовать для этого User Timings API.

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

Если у вас есть вопросы или комментарии, свяжитесь с нами.

Ссылки и авторства