Использование React-профилировщика

внешний интерфейс JavaScript React.js
Использование React-профилировщика

沈炼.jpg

Это первые 115 не поливают оригинал, я хочу получить более хороший оригинальный текст, ищите количество общественных забот о нас ~ Эта статья впервые появилась в правительстве, чтобы принять блог облачного интерфейса:Использование React-профилировщика

Использование React-профилировщика

предисловие

Обычно, когда вы разрабатываете проект, иногда вы чувствуете, что проект застрял.Обычно вы можете сразу внести исправления, но иногда бывает непросто найти точку, которая вызывает зависание, или трудно найти потенциальные проблемы с производительностью.React Developer Toolsкоторый предоставилProfilerОн может интуитивно помочь вам найти узкое место в производительности в проекте React и еще больше улучшить наше приложение.Рекомендуется всем установить и использовать.

  • Концептуально React работает в две фазы, и график жизненного цикла React выглядит так:

    • рендерингопределит, какие изменения необходимо внести, например, в DOM. Реагировать на звонки на этом этапеrender, затем сравните результат с последним визуализированным результатом.

    • этап фиксацииПроисходит при изменении приложения React. На этом этапе React также вызоветcomponentDidMountа такжеcomponentDidUpdateметоды жизненного цикла, такие как . (Для React DOM это происходит, когда React вставляет, обновляет и удаляет узлы DOM.)

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

использовать

Установить

ОтМагазин приложений Chrome,Расширение для браузера Фаерфокс,Пакет узлаЗагрузить и установить;

официальная документация.

представлять

  • renderedпричина

  • renders компонент

демо

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

 import React from "react";
 const style = {
   display: "flex",
   justifyContent: "space-around",
   maxWidth: 800,
   margin: "0 auto",
   padding: 60,
 };
 const Display = (props) => {
   console.log("Display");
   return <pre>{JSON.stringify(props.data, null, 2)}</pre>;
 };
 const Count = (props) => {
   console.log("count");
   return <p>{props.data}</p>;
 };
 // Anonymous
 export default class extends React.Component {
   state = {
     count: 0,
   };
   handleAdd = () => {
     this.setState({
       count: this.state.count + 1,
     });
   };
   onChange = (key) => (e) => {
     this.setState({
       [key]: e.target.value,
     });
   };
   render() {
     const { text, password, count } = this.state;
     return (
       <div>
         <div style={style}>
           <div>
             <input type="text" value={text || ""} onChange={this.onChange("text")} />
             <br />
             <br />
             <input type="text" value={password || ""} onChange={this.onChange("password")} />
           </div>
           <Display data={{ text, password }} />
         </div>
         <div align="center">
           <Count data={count} />
           <button onClick={this.handleAdd}>add</button>
         </div>
       </div>
     );
   }
 }

Действуйте следующим образом:

1. Нажмите кнопку перезагрузки и дождитесь завершения загрузки страницы;

2. Введите контент во входные данные, чтобы страница появиласьrender;

3, нажмите кнопку «Добавить» еще раз, чтобы снова создать страницу.render ;

потомProfiler

AпредставитьКоличество раз каждый столбец представляет собой представленные данные.

  • Цвет и высота столбцов соответствуют времени, необходимое для рендеринга этого фиксатора (более высокие желтые, чем более короткие зеленые);

  • Мы можем игнорировать самый короткий серый столбец, серый цвет означает отсутствие повторного рендеринга;

AНашим шагам соответствуют 6 столбцов района:

  • Первый столбец соответствует монтированию страницы, потому что это первый рендеринг, поэтому он самый высокий, что означает самое долгое время;

  • Второй и третий столбцы соответствуют двум рендерингам, вызванным введенным текстом;

  • Последние три столбца соответствуют рендерингу, вызванному тремя щелчками кнопки добавления.

переключаться влево и вправоAДанные области, указывающие на то, что информация о представлении выбранного столбца будет отображаться вBОбласть, в то же времяC

  • Committed at

  • Render durationЭта подача представляет собой потребление времени оказания, нам нужно сосредоточиться на этом;

Например06/11Этот коммит, весьAnonymousиспользуемый компонент1msРендерировать, но только провел себя0.2ms, На рисунке0.2ms of 1ms, оставшиеся0.8msИспользуется при рендеринге его дочерних элементов. ПодсборкаDisplayа такжеCountУ него также есть собственное соответствующее время рендеринга и так далее.

  • Ширина и цвет компонента указывают время, необходимое для рендеринга, а время желтого цвета также больше;

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

Например10/11Это представление, операция просто нажмите кнопку добавления, чтобы обновитьCount, но здесьDisplayНо он самый затратный по времени.

  • Нажмите, чтобы выбратьDisplay, который можно увидеть 6 раз справа renderedИнформация вышеWhy did this render?Записывайте каждый разrenderedс причин;

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

  • <>Вы можете просмотреть исходный код;

  • 🐞Информация о компонентах может быть напечатана на консоли;

предотвратить повторный рендеринг

ИзменятьDisplayа такжеCountФормулировка для обеспечения того, чтобы два компонентаreRenderПросто потому, что его собственные атрибуты изменились, давайте посмотрим на эффект.

 const Display = React.memo(
   (props) => {
     console.log("Display");
     return <pre>{JSON.stringify(props.data, null, 2)}</pre>;
   },
   (prev, next) => {
     return JSON.stringify(prev) === JSON.stringify(next);
   }
 );
 const Count = React.memo((props) => {
   console.log("count");
   return <p>{props.data}</p>;
 });

Повторите вышеуказанную операцию еще раз и посмотрите на результат.

жаль, хотяDisplayсуществуетReact.memoПри функции сравнения больше не повторяется.render. ноDisplayВремя рендеринга приложения и время рендеринга приложения стали больше, чем до перезаписи, а это значит, чтоmemoВремя сравнения функции больше, чем время рендеринга самого компонента.В текущем простом приложенииReact.memoНе стоит пытаться «оптимизировать» приложение.

Улучшать

Теперь мы знаем, как читатьProfilerreRender

import { List, Avatar } from "antd";
const Length100List = ({ data }) => {
  return (
    <List
      itemLayout="horizontal"
      dataSource={data}
      renderItem={(item) => (
        <List.Item key={item.id}>
          <List.Item.Meta
            avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
            title={item.name.last}
            description={item.email}
          />
          <div>{item.nat}</div>
        </List.Item>
      )}
    />
  );
};
// list 代表一个长度为100的数组,取自 https://randomuser.me/api/?results=100&inc=name,gender,email,nat&noinfo
<div style={style2}>
  <Length100List data={list} />
</div>;

render ProfilerЗаписанная информация выглядит следующим образом:

Очевидно, что неоптимизированныйLength100Listзанимает большую частьcommitвремя, которое явно не нужно, мы используемReact.memoостановитьсяListненужный рендеринг.

const PureListItem = React.memo(({ item }) => {
  return (
    <List.Item key={item.id}>
      <List.Item.Meta
        avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
        title={item.name.last}
        description={item.email}
      />
      <div>{item.nat}</div>
    </List.Item>
  );
});
const Length100List = React.memo(({ data }) => {
  return <List itemLayout="horizontal" dataSource={data} renderItem={(item) => <PureListItem item={item} />} />;
});

Посмотрите еще раз на эффект:

СейчасcommitСамый длинный — это когда мы нажимаем кнопку «Добавить», чтобы обновить данные. Что ж, доволен!

Метод оптимизации

  • shouldComponentUpdate()

Для разных бизнес-сценариев функция сравнения здесь будет написана по-разному, например, просто сравнениеpropsсвойство , или как в примерах в этой статье сJSON.stringifyнапрямую сравниватьprops. Для сложных структур данных, если вам нужно заблокироватьreRender, не рекомендуется выполнять глубокие сравнения или использоватьJSON.stringify, что сильно влияет на КПД. может рассмотреть возможность использованияimmutableдля ускорения сравнения вложенных данных, наimmutableиспользовать, вы можете просмотретьИзучите неизменяемость за 15 минут. Вы можете пойти, чтобы понять ихCustomComponentPureComponent

  • shouldComponentUpdatefalse(имеется в виду хороший крюк Дафа);
  • Из-за функциональных компонентов иhookИспользование таких сценариев оптимизации значительно сократилось;
import React from "react";
import { is } from "immutable";
export default class extends React.Component {
  shouldComponentUpdate(nextProps = {}, nextState = {}) {
    if (
      Object.keys(this.props).length !== Object.keys(nextProps).length ||
      Object.keys(this.state).length !== Object.keys(nextState).length
    ) {
      return true;
    }
    for (const key in nextProps) {
      if (!is(this.props[key], nextProps[key])) {
        return true;
      }
    }
    for (const key in nextState) {
      if (!is(this.state[key], nextState[key])) {
        return true;
      }
    }
    return false;
  }
}
  • React.PureComponent

    React.PureComponentполагаться наshouldComponentUpdateреализован слойshallowEqual, только для поверхностного сравнения объектов, чтобы уменьшить возможность пропуска обновлений, но если объект содержит сложные структуры данных, это может привести к ложным выравниваниям, поэтомуPureComponentбудет больше использоваться в более простыхprops & stateна дисплее компонента.

    React.memoТо же, что и его принцип, только для函数组件, возвращаемое значение функции обратного вызова такое же, какshouldComponentUpdateНапротив;

  • Hook

    Реагировать, чтобы обеспечить такиеuseEffect,useMemo,useCallback Такие как функция крюка, они представленыmemoizedсвойства, их вторым параметром является массив значений, при изменении данных массива значений,hook函数会重新执行。 несмотря на то чтоhookРешите некоторые болевые точки, такие как компоненты, ноhookСравните зависимости. Надеются все еще больные точки, и вот зависимость иногда очень долго, сообщество все еще должно принять официальный спрос - добавить пользовательские функции, но и данные официальные функции自定义hookЭто уже может помочь нам удовлетворить такие потребности.

    // customEquals: lodash.isEqual、Immutable.is、dequal.deepEqual 等;
    const useOriginalCopy = (value) => {
      const copy = React.useRef();
      const diffRef = React.useRef(0);
      if (!customEquals(value, copy.current)) {
        copy.current = value;
        diffRef.current += 1;
      }
      return [diffRef.current];
    };
    

Суммировать

О проекте РеактreRenderОптимизация всегда была банальной проблемой, каждый может более-менее обобщить собственный опыт в проекте, например, пакетные обновления, непрозрачные пропсы, использование режима публикации-подписки. Более того, в функциональном программировании, поддерживаемом React, обычно количество кода в компоненте не должно быть слишком большим, что требует больше разработчиков для доработки компонента, и легче контролировать свойства и состояние компонента. непонятно, почему это произошлоreRenderкогда,React Profilerявляется ответом.

использованная литература

Реагировать на оптимизацию производительности

Введение в React Profiler

Use the React Profiler for Performance

Повысьте производительность приложения с помощью React Hooks и инструментов отладки

React Issuse 16221

Изучите неизменяемость за 15 минут

Рекомендуемое чтение

Минимальные запасы для электронной коммерции — артикул и реализация алгоритма

Что нужно знать об управлении проектами

Как построить глобальную систему поиска кода от 0 до 1

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

работы с открытым исходным кодом

  • Zhengcaiyun интерфейсный таблоид

адрес с открытым исходным кодомwww.zoo.team/openweekly/(На главной странице официального сайта таблоида есть группа обмена WeChat)

Карьера

ZooTeam, молодая, увлеченная и творческая команда, связанная с отделом исследований и разработок продукции Zhengcaiyun, базируется в живописном Ханчжоу. В настоящее время в команде более 50 фронтенд-партнеров, средний возраст которых составляет 27 лет, и почти 30% из них — инженеры с полным стеком, настоящая молодежная штурмовая группа. В состав членов входят «ветераны» солдат из Ali и NetEase, а также первокурсники из Чжэцзянского университета, Университета науки и технологий Китая, Университета Хандянь и других школ. В дополнение к ежедневным деловым связям, команда также проводит технические исследования и фактические боевые действия в области системы материалов, инженерной платформы, строительной платформы, производительности, облачных приложений, анализа и визуализации данных, а также продвигает и внедряет ряд внутренних технологий. Откройте для себя новые горизонты передовых технологических систем.

Если вы хотите измениться, вас забрасывают вещами, и вы надеетесь начать их бросать; если вы хотите измениться, вам сказали, что вам нужно больше идей, но вы не можете сломать игру; если вы хотите изменить , у вас есть возможность добиться этого результата, но вы не нужны; если вы хотите изменить то, чего хотите достичь, вам нужна команда для поддержки, но вам некуда вести людей; если вы хотите изменить установившийся ритм, это будет "5 лет рабочего времени и 3 года стажа работы"; если вы хотите изменить исходный Понимание хорошее, но всегда есть размытие того слоя оконной бумаги.. , Если вы верите в силу веры, верьте, что обычные люди могут достичь необыкновенных вещей, и верьте, что они могут встретить лучшего себя. Если вы хотите участвовать в процессе становления бизнеса и лично способствовать росту фронтенд-команды с глубоким пониманием бизнеса, надежной технической системой, технологиями, создающими ценность, и побочным влиянием, я думаю, что мы должны говорить. В любое время, ожидая, пока вы что-нибудь напишете, отправьте это наZooTeam@cai-inc.com