Рубрики
Без рубрики

Топ 5 практик для повышения производительности реагирования

Не уверены, как ускорить свое приложение React? Узнайте о различных методах и практиках, которые должны помочь вам измерить узкие места производительности и оптимизировать ваши компоненты.

Автор оригинала: Manjunath.

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

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

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

Реагниалогические основы – так, что происходит под капотом?

Давайте начнем с DOM. Дом, как вы уже можете знать, создают дерево объектов и узлов. Элементы HTML становятся узлами в доме. В Условиях Mayman это стандарт, который определяет, как получить, изменять, добавлять или удалять элементы HTML. Однако DOM не был создан с учетом динамического пользовательского интерфейса. Когда DOM должен быть обновлен, он должен пройти через стадию COLLOWL/макета, а узлы DOM должны быть перекрашены, что медленно. Когда у вас есть приложение с тысячами

S, существует серьезная производительность.

Phonegapoptperf1.png.

Реагирование использует другую стратегию для обновления вашего DOM. Процесс широко известен как Примирение Отказ Когда ваш браузер изначально отображает ваше приложение, Rect создает дерево элементов. Давайте представим, что это, как реагировать на дерево:

React-Tutorial.jpg.

Но что, когда государственные изменения компонента, Render () Метод возвращает другое дерево элементов реагирования. Реагистрация должна рассчитать изменения, которые необходимо сделать до DOM, и он делает это, создавая виртуальный дом, а затем сравниваю это на реальном доме.

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

Реагистрационные компоненты-грязные .jpg

Однако дифференциальный алгоритм не идеален. Если обновленные опоры были переданы от COM RACK, заканчиваются обновлением всего подседа.

React - Virtual DOM-Best-Fruitics.jpg

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

Реактивно-компонент-примирение.jpg

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

Benchmark Ваше приложение для улучшения производительности – Инструменты и техники

Прежде чем прыгать на любые выводы, вы должны рассмотреть бенсмаркинг приложение, чтобы увидеть, насколько хорошо выполняется приложение. Реагируйте, используемые для того, чтобы иметь инструмент, называемый React-Addon-Perf, который был недавно на пенсии, и он не доступен в последней версии реагирования. Вместо этого Rect рекомендует использовать инструменты профилирования браузера, чтобы получить тот же результат.

Я лично предпочитаю инструменты разработчика Chrome, поскольку вкладка «Функции» находятся тонны функций, которые позволяют профилировать и отладки приложения с легкостью. Чтобы создать профиль производительности для вашего приложения, выполните следующие действия:

  1. Убедитесь, что вы экспортировали JS с помощью исходных карт или которые вы находитесь в режиме разработки.
  2. Временно отключите все расширения Ractions, такие как Rect Devtools, поскольку они могут повлиять на результаты.
  3. Настройте инструмент профилирования. Откройте инструменты разработчика Chrome и перейдите на вкладку Performance. Вы можете замедлить выполнение JavaScript, чтобы проблемы с производительностью становятся более очевидными.
  4. Теперь перейдите к странице, которую вы хотели бы профилировать, а затем нажмите красную кнопку, которая написана «запись». Если вы хотите создать производительность трассировки исходного визуализации, вы должны выбрать кнопку Profific и Reload. Теперь выполните желаемое действие и остановите запись.
  5. Chrome вернет визуализацию данных производительности в вертикальных полосах. Увеличение увеличения на полосу времени пользователя, чтобы увидеть производительность каждого компонента.
  6. Вы можете выбрать отдельные компоненты, а входная вкладка даст вам информацию о деятельности, которые занимают большую часть времени.

Для более подробного обзора я бы порекомендовал статью Бен Шварца о отладке реагирования.

Также есть библиотека, известная как WHY-DID-UN-UPDATE, это отличный инструмент для анализа компонентов. Это дает вам визуализацию реквизитов до и после и уведомляет вас о компонентах, которые не должны были быть перенаправлены. Чтобы установить инструмент, запустить

NPM установить –save почему-что-вы-обновление

Добавьте этот код в файл index.js.

import React from 'react';

if (process.env.NODE_ENV !== 'production') {
  const {whyDidYouUpdate} = require('why-did-you-update');
  whyDidYouUpdate(React);
}

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

Снятый на экран 2018-05-22 в 5.20.40 PM.PNG

Предотвратить ненужное рендеринг

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

Чтобы изменить реализацию по умолчанию, вы можете использовать крючок жизненного цикла SOCECOMPONENTUPDATE (). Этот крючок жизненного цикла не вызывается во время начального рендера, но только на последующих повторных рендерах. SOCCOMPONENTUPDATE () срабатывает, когда реквизиты изменились, и он возвращает true по умолчанию.

shouldComponentUpdate(nextProps, nextState) {
  return true;
}

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

class ListItem extends Component {
    shouldComponentUpdate(nextProps, nextState) {
     return false
    }
    
    render() {
    // Let the new props flow, I am not rendering again.
    }
}

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

class ListItem extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        return nextProps.isFavourite != this.props.isFavourite;
    }
    ...
}

Здесь мы проверяем ли текущее значение Isfavourite Изменился перед каждым визуальным (NextProps удерживает новое значение опоры) и если да, выражение возвращает true. Компонент восстанавливается. Изменения в любых других реквизитах не будут вызвать рендер (), поскольку мы не сравниваем их в должен () Отказ

Как насчет отреагирования .purecomponent?

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

React.purecomponent в значительной степени похоже на нормальный компонент, но ключевое различие, это обрабатывает должен () Метод для вас. Когда реквизит или государственное обновление, PUREComponent будет делать неглубокий Сравнение на них и обновить состояние.

Итак, что такое неглубокое сравнение? Вот выдержка из ответа на Stackoverflow :

Неглубокое сравнение требует проверки на равенство. При сравнении скалярных значений (цифр, строк) это сравнивает их значения. При сравнении объектов он не сравнивает их атрибуты – сравниваются только их ссылки (например, они указывают на тот же объект?).

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

На мой взгляд, вы должны использовать PURECOMPONENT, только если у вас есть четкое понимание того, как работает неизменные данные, а также при использовании ForceUpdate () для обновления вашего компонента.

Debsis Dead Plandlers.

Эта концепция не специфична для реагирования или любой другой интерфейсной библиотеки. DEBOUNCE давно использовался в JavaScript, чтобы успешно запускать дорогие задачи, не препятствуя производительности. Функция Debousing может быть использована для задержки определенных событий, чтобы она не выпустила каждую миллисекунду. Это поможет вам ограничить количество вызовов API, обновления DOM и потребления времени. Например, когда вы набираете что-то в меню поиска, появится короткое задержка до того, как всплывают все предложения. Функция Debousing ограничивает звонки на обработчик событий Onchange. Во многих случаях запрос API обычно производится после того, как пользователь перестал печатать.

Позвольте мне сосредоточиться на стратегии дебангинга для входных обработчиков и обновлений DOM. Обработчики ввода являются потенциальной причиной вопросов производительности. Позвольте мне объяснить, как:

export default class SearchBar extends React.Component {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
  }
  onChange(e) {
    this.props.onChange(e.target.value);
  }
  render () {
    return (
      
      
    );
  }
}

На каждом изменении ввода мы называем это .proops.onchange (). Что, если есть долговечная последовательность действий внутри этого обратного вызова? Вот где депонзия приходит это удобно. Вы можете сделать что-то вроде этого:

import {debounce} from 'throttle-debounce';

export default class SearchBarWithDebounce extends React.Component {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
    this.onChangeDebounce = debounce( 300, 
         value => this.props.onChange(value)
    );
  }
  onChange(e) {
    this.onChangeDebounce(e.target.value);
  }
  render () {
    return (
      
    );
  }
}

Обновление DOM происходит после того, как пользователь закончил печатать, что именно то, что нам нужно. Если вам интересно дебактирование звонков AJAX, вы можете сделать что-то подобное:

import {debounce} from 'throttle-debounce';

export default class Comp extends Component {
  constructor(props) {
    super(props);
    this.callAPI = debounce(500, this.callAPI);
  }
  onChange(e) {
    this.callAPI(e.target.value);
  }
  callAjax(value) {
    console.log('value :: ', value);
    // AJAX call here
  }
  render() {
    return (
      
); } }

Оптимизация реагирования на производство

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

Вы можете использовать сетевую вкладку в инструментах разработчиков, чтобы увидеть, что на самом деле замедление. Размер объекта RaG Bundle – это обычно виновник, и вам нужно минимурить его, прежде чем нажать на производство. Если вы загрузили приложение с помощью приложения Create-raction-raction, вы можете получить производственную сборку, запустив сборку NPM Run.

Когда вы запускаете это, Create-raction-App будет минифицировать код, запугивать/снимать его (это происходит в результате минификации) и генерирует исходные карты. Конечный пользователь способен загружать сценарии быстрее, чем версия, которая не была полезной. Сгенерированные отображения исходных карт особенно удобны, если вы решите перемещаться по коду через консоль разработчиков. Источники загружаются по запросу, и вы можете удалить его до фактического развертывания.

Если вы используете WebPack, вы можете построить производственную среду, запустив WebPack-P. Реагистрация также предлагает продуктивные одноиместные файлы для реагирования и взаимодействия.



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

Оптимизация ресурса вашего приложения – другое, что вам нужно рассмотреть. Это не имеет ничего общего с реагированием, но действительно может ускорить ваше приложение. Такие ресурсы, как изображения, значки и другие медиа-файлы, могут замедлить приложение, если они отображаются несжатым. Вкладка «Сеть в инструментах разработчиков должна давать вам понимание». Если вы используете статические ресурсы, оптимизируйте и сжимаете их, прежде чем нажать на сервер. Используйте CDN, если ваш сервер и потенциальные пользователи не находятся в непосредственной близости. Вот хорошая статья, написанная Дэвидом Лазич, которая охватывает Оптимизация производства построить дальше Отказ

Микро оптимизации для повышения производительности реагирования

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

Функциональные компоненты против классов компонентов

Вы, возможно, уже знаете, что большинство разработчиков реагирования предпочитают разделять свои компоненты на основе логики, которая входит в эти компоненты – Функциональные компоненты и компоненты класса Отказ Функциональные компоненты легче писать и прочитать, и они особенно полезны для создания пользовательского интерфейса или презентационного уровня. Компоненты класса, с другой стороны, идеально подходят для строительных контейнеров. Контейнеры делают вызовы API, отправляют действия в магазин и используют состояние для хранения данных. Затем они передают данные как реквизиты к презентационным компонентам.

До реакции V16 не было выпущено, как функциональные компоненты, так и компоненты класса имели одинаковый путь кода. Хотя функциональные компоненты, казалось, имели меньше строк кода, они не были ни оптимизированы, а также не предлагали улучшения скорости, потому что они были преобразованы в классные компоненты под капотом. Однако сценарий изменился с выпуском V6.

Вот выдержка из Официальные документы :

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

Функция связывания рано

Функции связывания в методе рендеринга () – это плохое представление, потому что реагирование создаст новую функцию на каждом рендере.

class Button extends React.Component {
  handleClick() {
    console.log('Yay!');
  }

  render() {
    return (
      

Функции стрелки внутри метода рендеринга тоже плохо, к сожалению, к сожалению.

class Button extends React.Component {
  handleClick() {
    console.log('Yay');
  }

  render() {
    return (
      

Процесс создания новой функции обычно быстро и не замедлит вас, если честно. Но если вы реализовали SOCCOMPONENTUPDATE () или, если вы используете PUREComponent Base Class, React видит новые реквизиты на каждом рендере, а дочерние компоненты воспроизводятся без необходимости.

Чтобы исправить эту проблему, вы можете привязать функции раннее, как это:

class Button extends React.Component {
  constructor(props) {
    super(props);

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log('Yay!');
  }

  render() {
    return (
      

В качестве альтернативы вы можете использовать такие поля экземпляра класса. Тем не менее, это экспериментальная особенность, которая еще не добралась до стандартов. Но вы можете использовать его в вашем проекте с помощью Babel.

class Button extends React.Component {
  // This is a class field
  handleClick = () => {
    console.log('Yay!');
  }

  render() {
    return (
      

Окончательные слова

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

Если вам есть что поделиться, дайте нам знать в комментариях.