Назад

Как повысить производительность React приложений

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

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

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

Откуда взялся миф о супер быстром React?

Я думаю, когда вы только услышали про React впервые, то наверняка слышали утверждение, что React быстрый, потому что он работает с Virtual DOM. Да, это так. В него заложена идея работы с виртуальным DOM (который никакой не DOM, а просто дерево Javascript объектов), который позволяет нам делать минимальные изменения в реальном DOM (потому, что он оооочень медленный). Таким образом, React, работая с виртуальным DOM делает все изменения, вычисляет разницу с предыдущим состоянием и вносит эти изменения в реальный DOM. За счет этого подхода мы действительно выигрываем в производительности, но это только начало!

А should ли component update?

Возможно вы слышали о таком методе жизненного цикла React, как shouldComponentUpdate. Это самый простой и очевидный способ решения проблем с производительностью. Если вы не определили его, то он всегда возвращает true. Если же он, после сравнения своих текущих и пришедших props, возвращает false, то React просто не запускает метод render (перевычислений DOM для них так же не происходит). За счет этого и время исполнения кода уменьшается, памяти занимается меньше и т.д. Для упрощения решения этой задачи в последних версиях React появился PureComponent. Это почти тот же React.Component, но, вместо простого возврата true, его метод shouldComponentUpdate проводит неглубокое сравнение всех пришедших props.

Казалось бы - вот она панацея, но тут тоже есть свои подводные камни.

Объекты и массивы

Напомню, что, в отличии от примитивных типов, два объекта нельзя просто сравнить при помощи == или ===. Если вы передаете в свой компонент объект, которые имеет большую вложенность (свойства объекта так же являются объектами) можно сравнить при помощи глубокого сравнения, но это, возможно, будет не самой лучшей идеей. Это может, наоборот, негативно сказаться на производительности. Особенно это касается массивов таких объектов. Для решения этой проблемы вы можете перейти к иммутабельных объектам.

Иммутабельные объекты - это такие объекты, которые не изменяются. Это может быть обычный Javascript объект, но вместо того, чтобы менять его свойства, вы создаете новый. Приведу пример.

// Мутабельный объект
let mutable = { foo: true, bar: false };
mutable.bar = true;

// Иммутабельный объект
let immutable =  { foo: true, bar: false };
immutable = Object.assign({}, immutable, { bar: true });

shouldComponentUpdate (nextProps) {
    this.props.mutable === nextProps.mutable // true
    this.props.immutable === nextProps.immutable // false
}

Конечно, в данном примере иммутабельность объекта всего-лишь условность и вам придется следить, чтобы его свойства никогда не менялись, чтобы гарантировать правильность работы приложения. Для упрощения этой задачи вы можете воспользоваться какими-нибудь библиотеками, например Immutable.js.

Псевдоновые props

Под этим я понимаю такие props, которые логически новыми не являются, но фактически они другие. Звучит запутанно? Я думаю на примере вы все поймете.

<MyComponent onChange={(e) => { ... }} settings={{ foo: 'bar' }} />

Встречались с таким? Так вот, при каждом вызове render родительского компонента в MyComponent попадет новая функция и новый объект. И shouldComponentUpdate вам тут уже не поможет. Решение этой проблемы очень простое. Просто сделайте их свойствами родительского класса. В следующем примере все ок.

<MyComponent onChange={this.handleChange} settings={this.settings} />

Заключение

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

Зачем мне фотоаппарат в 2018?

Зачем мне использовать семантические теги, ARIA роли и атрибуты