JavaRush /Курсы /Модуль 3: React /Профилирование и инструменты для анализа производительнос...

Профилирование и инструменты для анализа производительности — React DevTools

Модуль 3: React
3 уровень , 7 лекция
Открыта

Введение в профилирование компонентов

Что такое профилирование и зачем оно нужно?

Профилирование — это процесс анализа производительности вашего приложения. Это как медицинское обследование, только ваше приложение здесь как пациент. Задача профилирования — определить, какие компоненты работают слишком медленно, где происходят лишние рендеры и почему UI ощущается как слон на батуте.

Без профилирования вы, возможно, догадывались, что где-то в коде есть проблемы. Но где? И почему? Вот тут-то профилирование и становится настоящим спасателем.

Зачем вообще искать проблемные места?

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

  • Медленные обновления интерфейса. Пользователь жмёт кнопку, а интерфейс обновляется с задержкой.
  • Долгие начальные загрузки. Приложение открывается так долго, что пользователь успевает сделать чай.
  • Частые подвисания. Скроллинг списка прерывается, как будто ваш React соревнуется с вашим терпением.

React DevTools — ваш помощник в борьбе с замедлениями

Что такое React DevTools?

React DevTools — это расширение для браузера (поддерживаются Chrome, Firefox и Edge), которое позволяет исследовать компоненты и их рендеры в React-приложении. Оно также предоставляет вкладку Profiler, где можно изучить, какие компоненты занимают больше всего времени при рендере.

Вы можете установить React DevTools из Chrome Web Store или Firefox Add-ons.

Установка React DevTools

Прежде чем начать, убедитесь, что ваше приложение работает в режиме разработки (development). В противном случае React DevTools может не отображать всю полезную информацию.

После установки:

  1. Откройте своё приложение в браузере.
  2. Перейдите в инструменты разработчика (DevTools) и найдите вкладку Components или Profiler.
  3. Готово! Теперь вы можете наблюдать структуру вашего приложения и его поведение.

Использование вкладки Profiler

Как включить профилирование?

  1. Перейдите во вкладку Profiler в React DevTools.
  2. Нажмите кнопку "Start profiling" (Запуск профилирования).
  3. Взаимодействуйте с приложением: кликайте кнопки, открывайте модальные окна, скрольте списки.
  4. Нажмите "Stop profiling" (Остановка профилирования), чтобы завершить сбор данных.

Анализ профилирования: основные термины

Когда вы откроете результат профилирования, перед вами появится нечто похожее на цветной график и список. Не пугайтесь, мы сейчас всё разберём:

  • Commit — это момент, когда React фиксирует изменения в DOM. Каждый "commit" отражает, сколько времени потребовалось на обновление у различных компонент.
  • Flame Graph — флеймграф (или "огненный график"), показывающий, сколько времени каждый компонент затратил на рендер. Чем шире блок, тем больше времени он потребовал.
  • Ranked Graph — ранжированный график с сортировкой компонент по времени рендера. Очень удобно, если вы хотите сразу перейти к самым "жирным" компонентам.

Пример анализа профиля

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

1. Вы записываете взаимодействие

Вы нажимаете "Start Profiling" и добавляете новую задачу в список.

2. Смотрите на Flame Graph

Вы видите, что компонент TodoList (список задач) стал очень широким. Упс! Это значит, что он потребовал слишком много времени на рендеринг.

3. Ищете причину

Может быть, вы забыли обернуть этот компонент в React.memo? Или его пропсы меняются чаще, чем нужно? Например, объект пропсов создаётся заново при каждом рендере.

Выявление проблемных мест

Лишние рендеры

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

Как найти лишние рендеры?

  1. Используйте профилировщик — ищите компоненты, которые рендерятся слишком часто.
  2. Проверьте зависимости в хуках (например, useCallback или useMemo). Возможно, вы забыли правильно указать их.
  3. Убедитесь, что компонент обёрнут в React.memo, если это необходимо.

Тяжёлые вычисления

Если в вашем приложении есть сложные вычисления (например, фильтрация большого массива), их можно оптимизировать с помощью useMemo.

Как найти тяжёлые вычисления?

  1. Ищите в профилировщике компоненты, которые занимают слишком много времени на рендеринг.
  2. Проверьте, нужно ли мемоизировать вычисления с помощью useMemo.

Советы по оптимизации

  1. Профилируйте в реальных условиях. Всегда тестируйте производительность в максимально приближённых к реальным условиях. Например, используйте список данных аналогичного размера, который будет в реальном приложении.

  2. Проверяйте зависимости мемоизаций. Убедитесь, что зависимости в массивах useCallback и useMemo указаны правильно. Если пропустить хотя бы одну зависимость, поведение приложения может стать непредсказуемым.

  3. Не мемоизируйте лишнего. Иногда мемоизация функций или значений требует больше ресурсов, чем их пересчёт. Пример: если функция лёгкая, то мемоизировать её нет смысла.

Пример профилирования на реальном приложении

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

Компоненты:

  • UsersList — отображает список пользователей.
  • UserItem — отдельный пользователь.
import React, { useState, useMemo } from "react";

interface User {
  id: number;
  name: string;
}

const UserItem: React.FC<{ user: User }> = React.memo(({ user }) => {
  console.log(`Render UserItem: ${user.name}`);
  return <li>{user.name}</li>;
});

export const UsersList: React.FC = () => {
  const [users, setUsers] = useState<User[]>([
    { id: 1, name: "Alice" },
    { id: 2, name: "Bob" },
  ]);

  const addUser = () => {
    setUsers((prevUsers) => [
      ...prevUsers,
      { id: prevUsers.length + 1, name: `User ${prevUsers.length + 1}` },
    ]);
  };

  const memoizedUsers = useMemo(() => users, [users]);

  return (
    <div>
      <button onClick={addUser}>Add User</button>
    <ul>
        {memoizedUsers.map((user) => (
          <UserItem key={user.id} user={user} />
        ))}
      </ul>
    </div>
  );
};

Используем React.memo и useMemo для оптимизации. Теперь мы можем профилировать рендер и проверять, не рендерится ли UserItem зря.

1
Задача
Модуль 3: React, 3 уровень, 7 лекция
Недоступна
Установка React DevTools
Установка React DevTools
1
Задача
Модуль 3: React, 3 уровень, 7 лекция
Недоступна
Запуск и анализ профилирования
Запуск и анализ профилирования
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ