Главная / Статьи

Чтение трекеров производительности React в Chrome DevTools для выявления медленной отрисовки

Узнайте, как функции Scheduler, Components и Server в React 19.2 показывают, где тратится время на медленные операции, а также как использовать рабочий процесс «запись-исправление-запись» для принятия мер.

Издатель: REACTAPP.TOP5 мин чтения1081 слов

Источники: Stop Guessing Why React Is Slow. Use the Performance Timeline.

Когда взаимодействие с React кажется медленным, первым побуждением является добавление useMemo, useCallback и React.memo в надежде на улучшение. Однако страница часто остается медленной, потому что никто не измерял, что именно занимает время. В React 19.2 появились Performance Tracks, которые записывают деятельность React во временную шкалу производительности браузера; здесь описано, что показывает каждая из этих записей, и как превратить запись в конкретное решение проблемы.

Почему обычная временная шкала была трудна для чтения

Если записать медленное взаимодействие в панели Performance инструментов разработчика Chrome для приложения без этих трекеров, основной поток обычно будет выглядеть так:

JavaScript
████████████████████
██████████
███
████████████

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

Что добавляют трекеры React

React предоставляет специальные трекеры для трех областей:

Scheduler
Components
Server

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

USER CLICK
    │
    ▼
┌─────────────────────────────┐
│ React Scheduler             │
│ Blocking → Render → Commit  │
├─────────────────────────────┤
│ React Components            │
│ Dashboard                   │
│ ├─ Header                   │
│ ├─ DataTable  ← expensive   │
│ └─ Chart                    │
├─────────────────────────────┤
│ Network / JavaScript        │
└─────────────────────────────┘

Ценность заключается в корреляции: активность React и активность браузера отображаются на одной общей временной оси.

Шедулер: почему эта задача была выполнена сейчас?

React не обрабатывает каждое обновление одинаково. Механизм планирования разделяет задачи по приоритету с использованием категорий вроде Blocking, Transition, Suspense и Idle, а также обозначает этапы каждого обновления: Update, Render, Commit и любые оставшиеся операции Effects.

Это позволяет ответить на вопросы вроде «почему возникают задержки при вводе текста в это поле?». Логи могут показать, что нажатие клавиши запустило тяжелую синхронную обработку в категории Blocking. Или же может оказаться, что ресурсоемкая операция уже была правильно помещена в категорию Transition, что указывает на другую причину. В любом случае вы работаете на основе фактов, а не интуиции. Если концепция категорий Transition и приоритетов нова для вас, модель, лежащая в основе этих категорий, описана в статье Understanding React Lanes.

Компоненты: кто выполнил работу?

Для повседневной отладки это обычно самый полезный инструмент. Он отображает в виде флеймграфа, сколько времени каждый компонент тратил на отрисовку и выполнение эффектов, а во время разработки также позволяет выделить измененные свойства и последовательные обновления. Типичный результат выглядит так:

ProductPage        310ms
├── Header           12ms
├── Filters          18ms
├── DataTable       245ms  ←
└── Footer            8ms

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

Сервер: ждет ли страница вообще React?

В приложениях, использующих React Server Components, во время разработки также отображаются запросы к серверу и работа серверных компонентов на графике времени. Это помогает выявить распространенную ошибку диагностики:

Slow page
   │
   ▼
Assume React render
   │
   X
   │
   ▼
Actually waiting on:
getProducts()
      │
      ▼
Database / API

Если трейс показывает, что страница простаивает во время ожидания функцией getProducts() ответа от базы данных или API, решение должно касаться процесса получения данных — например, использования кэширования, параллельных запросов или более эффективных запросов; использование React.memo для обертки компонентов не поможет. Именно поэтому важно видеть всю временную шкалу выполнения в одном отображении.

Повторяемый процесс отладки

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

1. Reproduce the problem
          ↓
2. Open Performance
          ↓
3. Record the interaction
          ↓
4. Find the slow React work
          ↓
5. Inspect the component / phase
          ↓
6. Check network and browser work
          ↓
7. Fix the actual bottleneck
          ↓
8. Record again

Не пропускайте последний шаг. Запишите трейс снова в тех же условиях и сравните результаты. Оптимизация, которая никогда не проверялась заново, остается лишь гипотезой; иногда второй трейс показывает, что изменения лишь перенесли нагрузку в другое место, а не устранили её.

Знайте ограничения локального трейса

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

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

Основные выводы

Самой дорогостоящей привычкой, влияющей на производительность, является не неправильный выбор инструмента; это оптимизация до того, как будет понята суть проблемы. Более разумный подход выглядит следующим образом:

Slow interaction
       │
       ▼
    Measure
       │
       ▼
 Find the bottleneck
       │
 ┌─────┼──────┐
 ▼     ▼      ▼
React Network Browser
 │      │      │
 ▼      ▼      ▼
Fix    Fix    Fix
  • Сначала измеряйте: треки делают запись данных и выявление узких мест простыми задачами.
  • Используйте трек Планировщика, чтобы понять приоритеты и этапы выполнения, а также трек Компонентов для поиска дорогостоящих поддеревьев.
  • Перед тем как предположить, что проблема в процессе отрисовки, проверьте трек Сервера и сетевые каналы.
  • После каждой изменения перезаписывайте данные, чтобы подтвердить эффективность исправления.
  • Рассматривайте локальные отчеты как инструмент диагностики, а для понимания того, что испытывают пользователи, опирайтесь на данные с полей.

Такой подход позволяет сместить фокус с вопроса о необходимости использования useMemo на выяснение того, что на самом деле потребовало 200 миллисекунд, и именно этот вопрос приводит к реальному решению проблемы.