# Розподілення коду

Під час розробки застосунку всі файли проєкту обʼєднуються в один файл. збільшення коду збільшує і розмір кінцевого файлу. На пристроях із повільним зʼєднанням до мережі завантаження може займати суттєвий час аж до десятків секунд. Тому завантаження великих файлів на продакшені може бути проблемою.

<figure><img src="https://152171225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fd8ijY6Ec364QOX6LzJiP%2Fuploads%2F5XjmYAY5febviu1qam2M%2Fwebpack-bundle-output-illustration2.jpg?alt=media&#x26;token=98fda097-30bf-4d47-abac-7cc7e3a48b71" alt="" width="375"><figcaption></figcaption></figure>

Розв'язанням цієї проблеми може стати розбиття кінцевого файлу програми на дрібніші файли, які будуть вантажитися тільки тоді, коли виникне потреба. В цьому суть розбиття коду.&#x20;

<figure><img src="https://152171225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fd8ijY6Ec364QOX6LzJiP%2Fuploads%2Fsd7n4NGNYy2aArgC82Hq%2Freact-lazy-chunks-lazy-load.jpg?alt=media&#x26;token=9301e2ca-c978-40b0-9b39-890518ce479a" alt="" width="375"><figcaption></figcaption></figure>

При створенні React-застосунку за допомогою Create React App використовується збирач модулів Webpack. Він підтримує можливість розбиття коду.

Код можна розбивати за **маршрутами** (route-centric) і за **компонентами** (component-centric). У більшості проєктів найкраще підходить перший варіант. Який підхід вибрати - обирає сам розробник в залежності  від вимог до проєкту. Бажано знайти золоту середину - не робити громіздкі файди та не сильно дрібнити.

**Як визначитися як розбити код:**&#x20;

* Поділ коду на основі маршрутів - обов'язковий у будь-якому додатку.
* Поділ коду на основі компонентів роблять тільки у великих, складних інтерфейсах із сотнями компонентів та великими бібліотеками.
* Надмірний поділ коду - погана ідея. HTTP-запит за файлом може бути довше ніж додана вага до першого завантаження.

## React.lazy() та React.Suspense[​](https://textbook.edu.goit.global/react-zr7b4k/v1/uk/docs/lesson-10/code-splitting#reactlazy-%D1%82%D0%B0-reactsuspense) <a href="#reactlazy-ta-reactsuspense" id="reactlazy-ta-reactsuspense"></a>

Розглянемо стандартне підключення компонентів (сторінок) в роутах без поділу коду. Згори файлу проводимо імпорти.

{% code title="src/components/App.jsx" %}

```jsx
import Component from "path/to/Component";

const App = () => {
  return (
    <Routes>
      <Route path="/path" element={<Component />} />
      {/* Routes */}
    </Routes>
  );
};
```

{% endcode %}

У специфікації ES2020 є можливість динамічно імпортувати модулі. Замість звичайного імпорту <mark style="background-color:red;">import</mark> використовують функцію <mark style="background-color:red;">import()</mark>, яка повертає проміс, значення якого файл модуля.

```jsx
import("path/to/Component").then(module => console.log(module));
```

У React є можливість вказати, який код можна виділити в окремий файл і рендерти за потреби. Для асинхронного завантаження компонента існує функція <mark style="background-color:red;">React.lazy()</mark>. А компонент <mark style="background-color:red;">Suspense</mark> призупиняє його відображення до завершення завантаження.

Тепер розглянемо підключення компонентів з розподілом коду.

{% code title="src/components/App.jsx" %}

```jsx
import { lazy, Suspense } from "react";

const Component = lazy(() => import("path/to/Component"));

const App = () => {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/path" element={<Component />} />
        {/* Routes */}
      </Routes>
    </Suspense>
  );
};
```

{% endcode %}

Розберемо цей код. При підключенні компонента викликаємо метод <mark style="background-color:red;">lazy()</mark>, а в ньому анонімну колбек-функцію-завантажувач компонента <mark style="background-color:red;">import()</mark>.

Поки не завантажиться компонент буде відображатися заглушка  - компонент <mark style="background-color:red;">Suspense</mark>. У prop <mark style="background-color:red;">fallback</mark> передають або React-елемент, або компонент.

{% hint style="warning" %}
Якщо залишити статичний імпорт компонентів, як в першому прикдалі, то Webpack не виконає поділ коду і додасть весь код компоненту  в основний JavaScript файл проекту.
{% endhint %}

## Suspense та прийом «shared layout»[​](https://textbook.edu.goit.global/react-zr7b4k/v1/uk/docs/lesson-10/code-splitting#suspense-%D1%82%D0%B0-%D0%BF%D1%80%D0%B8%D0%B9%D0%BE%D0%BC-shared-layout) <a href="#suspense-ta-priiom-shared-layout" id="suspense-ta-priiom-shared-layout"></a>

При використанні прийому «shared layout» <mark style="background-color:red;">Suspense</mark> потрібно розташувати безпосередньо всередині компонента <mark style="background-color:red;">SharedLayout</mark> - огорнути ним <mark style="background-color:red;">Outlet</mark>. Якщо цього не зробити, то  будуть пропадати й повторно вантажитися компоненти загальної частини сторінок, як-то хедер, футер, бокове меню тощо.

{% code title="src/components/App.jsx" %}

```jsx
import { lazy } from "react";

const Component = lazy(() => import("path/to/Component"));

const App = () => {
  return (
    <Routes>
      <Route path="/" element={<SharedLayout />}>
        <Route path="path" element={<Component />} />
        {/* Routes */}
      </Route>
    </Routes>
  );
};
```

{% endcode %}

{% code title="src/components/SharedLayout.jsx" %}

```jsx
import { Suspense } from "react";
import { Outlet } from "react-router-dom";

const SharedLayout = () => {
  return (
    <Container>
      <AppBar>
        <Navigation />
        <UserMenu />
      </AppBar>

      <Suspense fallback={<div>Loading...</div>}>
        <Outlet />
      </Suspense>
    </Container>
  );
};
```

{% endcode %}

При вкладених маршрутах батьківському роуту треба також прописувати <mark style="background-color:red;">Suspense</mark>, щоб перемальовувалась не вся сторінка, а тільки частина вкладеного маршруту.

Зверніть увагу на компоненти [App](https://codesandbox.io/s/react-lazy-ta-react-suspense-j6lj7h?file=/src/components/App.js), [SharedLayout](https://codesandbox.io/s/react-lazy-ta-react-suspense-j6lj7h?file=/src/components/SharedLayout.jsx) та [About](https://codesandbox.io/s/react-lazy-ta-react-suspense-j6lj7h?file=/src/pages/About.jsx).

{% embed url="<https://codesandbox.io/s/react-lazy-ta-react-suspense-j6lj7h?file=/src/index.js>" %}

**Покликання:**&#x20;

[Про розбиття коду в React](https://linguinecode.com/post/code-splitting-react-router-with-react-lazy-and-react-suspense)
