Оптимизация React приложения с помощью React.lazy
Tags: react, frontend, webdev, javascript
Published: 2023-01-08 15:05:40

Если вы ищете способ оптимизировать свое React приложение, `React.lazy` — отличный инструмент, который стоит иметь под рукой. Он позволяет уменьшить размер бандла вашего приложения, отображая только те компоненты, которые нужны пользователю. Это понятие известно как “lazy-loading” («ленивая загрузка»), другими словами, компоненты загружаются только тогда, когда они необходимы. Чтобы лучше понять преимущества React.lazy, важно иметь общее представление о таких понятиях, как «бандлинг» и «разделение кода».

### Бандлинг
Проще говоря, «бандлинг» — это когда ваш импортированный код объединяется в один файл для загрузки всего приложения сразу. Ниже приведен простой пример того, как работает бандлинг:
`hi.js`

```jsx
export const sayHi = () => {
		return "Hi";
}
```

`index.js`

```jsx
import { sayHi } from './hi.js'

console.log(sayHi()); // Hi
```

Вот что происходит после объединения приложения:

```jsx
export const sayHi = () => {
		return "Hi";
}

console.log(sayHi()); // Hi
```

Логично, не так ли?

Связывание выполняется на уровне Webpack и доступно из коробки, если вы используете CRA, Next.js и другие подобные инструменты.

### Разделение кода

Таким образом, бандлинг определенно помогает нам, верно? Однако есть определенные случаи, которые следует учитывать. Когда ваше приложение вырастет, размер бандлинга тоже будет расти. Особенно когда мы используем сторонние библиотеки. Вот где в игру вступает разделение кода. Разделение кода — это процесс создания нескольких бандл пакетов, которые динамически загружаются во время ран тайма (выполнения). С разделением кода вы можете быть уверены, что в приложение загружается только тот код, который нужен пользователю в точное время. Условный рендеринг — неплохой вариант использования в этом сценарии. Давайте рассмотрим следующий фрагмент кода:

```jsx
...
import Component1 from './Component1.jsx';
import Component2 from './Component2.jsx';

function Container() {
  const [expanded, setExpanded] = useState(false);

  const handleChange = () => {
    setExpanded(!expanded);
  };

  return (
    <div>
      <button onClick={handleChange}>toggle</button>

      {expanded ? <Component1 /> : <Component2 />}
    </div>
  );
}

...
```

Я знаю, что этот пример, вероятно, слишком упрощен, но давайте представим, что `Component1` и `Component2` несут тяжелую бизнес-логику и в них много кода. Основываясь на условии, мы можем сказать, что мы используем только один из этих компонентов в любой момент времени, но поскольку мы импортируем их оба во время начальной загрузки страницы, мы неэффективно используем ресурсы и увеличиваем размер бандл пакета больше, чем необходимо. Это нехорошо, это означает, что пользователи могут испытывать проблемы с загрузкой и чувствовать, что приложение работает медленно.

### Р**азделение кода с помощью React.lazy**

`React.lazy` помогает динамически отображать компоненты с помощью динамического импорта. Он автоматически загрузит нужный бандл пакет при первой загрузке страницы.

`React.lazy` принимает функцию в качестве параметра с динамическим импортом в ней и возвращает `Promise`, содержащее разрешенный модуль с компонентом экспорта  по умолчанию. Поскольку процесс является асинхронным, компоненты с «ленивой загрузкой» должны быть заключены в компонент `Suspense`, который можно использовать для указания того, что модуль загружается. Вот предыдущий пример, но теперь с использованием `React.lazy`:

```jsx
...
import React, { Suspense } from 'react';

const Component1 = React.lazy(() => import('./Component1.jsx'));
const Component2 = React.lazy(() => import('./Component2.jsx'));

function Container() {
  const [expanded, setExpanded] = useState(false);

  const handleChange = () => {
    setExpanded(!expanded);
  };

  return (
    <div>
      <button onClick={handleChange}>toggle</button>

				<Suspense fallback={<div>Loading...</div>}>
		      {expanded ? <Component1 /> : <Component2 />}
				</Suspense>

    </div>
  );
}

...
```

`fallback` свойство в `Suspense` принимает любой компонент React, который может быть отрендерен при загрузке “ленивого” компонента.

 Есть гораздо больше и гораздо лучших вариантов использования `React.lazy`, например, разделение кода на основе раутинга. Обязательно ознакомьтесь с официальной [документацией](https://ru.reactjs.org/docs/code-splitting.html).

В этой статье мы подробно рассмотрели концепции бандлинга и разделения кода, а также то, как они связаны с оптимизацией приложения React. Мы также изучили использование `React.lazy` для отложенной загрузки компонентов и улучшения начальной загрузки приложения React. Поняв эти концепции и внедрив `React.lazy` в свои собственные проекты, вы сможете предпринять шаги для повышения производительности своего приложения React и обеспечения лучшего взаимодействия с пользователем. Я надеюсь, что эта статья помогла вам оптимизировать React приложение.