API для работы с Profiler

Profiler измеряет то, как часто рендерится React-приложение и какова «стоимость» этого. Его задача — помочь найти медленные части приложения, которые можно оптимизировать (например, через мемоизацию).

Примечание:

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

Для отладки на продакшене, React предоставляет специальную продакшен-сборку с включенным профилированием. Подробнее об использовании данной сборки можно узнать на fb.me/react-profiling.

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

Profiler может быть добавлен в любую часть React-дерева для измерения стоимости рендеринга этой части. Он принимает два пропа: id (string) и колбэк onRender (function), который React вызывает каждый раз, когда компонент внутри дерева «фиксирует» обновление.

Например, так выглядит процесс профилирования компонента Navigation и его дочерних компонентов:

render(
  <App>
    <Profiler id="Navigation" onRender={callback}>
      <Navigation {...props} />
    </Profiler>
    <Main {...props} />
  </App>
);

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

render(
  <App>
    <Profiler id="Navigation" onRender={callback}>
      <Navigation {...props} />
    </Profiler>
    <Profiler id="Main" onRender={callback}>
      <Main {...props} />
    </Profiler>
  </App>
);

Также Profiler может быть вложенным с целью замера разных компонентов внутри поддерева:

render(
  <App>
    <Profiler id="Panel" onRender={callback}>
      <Panel {...props}>
        <Profiler id="Content" onRender={callback}>
          <Content {...props} />
        </Profiler>
        <Profiler id="PreviewPane" onRender={callback}>
          <PreviewPane {...props} />
        </Profiler>
      </Panel>
    </Profiler>
  </App>
);

Примечание:

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

Колбэк onRender

Profiler принимает функцию onRender в качестве пропа. React вызывает эту функцию каждый раз, когда компонент внутри профилируемого дерева «фиксирует» изменение. Эта функция принимает параметры, которые описывают, что было отрендерено и сколько времени это заняло.

function onRenderCallback(
  id, // проп "id" из дерева компонента Profiler, для которого было зафиксировано изменение
  phase, // либо "mount" (если дерево было смонтировано), либо "update" (если дерево было повторно отрендерено)
  actualDuration, // время, затраченное на рендер зафиксированного обновления
  baseDuration, // предполагаемое время рендера всего поддерева без кеширования
  startTime, // когда React начал рендерить это обновление
  commitTime, // когда React зафиксировал это обновление
  interactions // Множество «взаимодействий» для данного обновления 
) {
  // Обработка или логирование результатов...
}

Давайте поближе рассмотрим каждый из пропсов:

  • id: string — Проп id из дерева компонента Profiler, для которого было зафиксировано изменение. Может использоваться для определения той части дерева, которое было зафиксировано, если вы используете несколько профилировщиков.
  • phase: "mount" | "update" — Показывает, было ли дерево только что смонтировано в первый раз или повторно отрендерено в результате изменения пропсов, состояния или хуков.
  • actualDuration: number — Время, затраченное на рендеринг компонента Profiler и его дочерних компонентов для текущего обновления. Показывает насколько хорошо поддерево использует мемоизацию (например, React.memo, useMemo, shouldComponentUpdate). В идеальном случае это значение должно существенно снизиться после монтирования, так как многим из дочерних компонентов нужно будет перерендериваться только в случае, если изменяются их специфичные пропсы.
  • baseDuration: number — Длительность самого последнего рендеринга для каждого отдельного компонента внутри дерева компонента Profiler. Это значение оценивает стоимость рендера в наихудшем случае (например, изначальное монтирование или дерево без мемоизации).
  • startTime: number — Временная метка, когда React начал рендерить текущее обновление.
  • commitTime: number — Временная метка, когда React зафиксировал текущее обновление. Это значение доступно для всех профилировщиков при фиксации, позволяя группировать их, если в этом есть необходимость.
  • interactions: Set — Множество «взаимодействий», которые были зафиксированы во время подготовки изменения (например, когда render или setState были вызваны).

Примечание:

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

Вы можете узнать подробнее на fb.me/react-interaction-tracing.