Lazy loading компонентов в React

При разработке больших приложений React мы обычно используем множество изображений и видео, устанавливаем сторонние пакеты/библиотеки, выполняем вызовы API и делаем множество других вещей. Это, естественно, увеличивает время, необходимое для загрузки нашего приложения, и приводит к огромному размеру пакета, что ухудшает взаимодействие с пользователем. Вот здесь-то и возникает ленивая загрузка . Это позволяет нам загружать контент вовремя , прямо перед его отображением в приложении. Мы можем избежать предварительной загрузки контента, пока он еще не виден, и сосредоточить все ресурсы на контенте, который находится в представлении.

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

Что такое lazy loading?

Когда мы запускаем веб-приложение React, оно обычно объединяет все приложение сразу, загружая для нас все, включая все страницы веб-приложения, изображения, контент и многое другое, что потенциально приводит к медленной загрузке и общей низкой производительности, в зависимости от размер контента и пропускная способность Интернета в данный момент.

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

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

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

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

Примечание. Одностраничные приложения (SPA) предназначены для размещения всех страниц и содержимого в одном документе/странице. Вот почему отложенная загрузка особенно полезна при разработке SPA.

Как реализовать lazy loading в React

До сих пор мы видели, что такое ленивая загрузка и почему ее важно реализовать. Теперь давайте посмотрим, как мы можем реализовать это в наших приложениях React, используя две функции React, которые упрощают реализацию разделения кода и отложенной загрузки — React.lazy() и React.Suspense .

React.lazy() — это функция, которая позволяет нам отображать динамический импорт так же, как и обычные компоненты. Использование динамического импорта вместе с React.lazy() позволит нам импортировать компонент непосредственно перед его отображением на экране. Важно отметить, что React.lazy() функция принимает функцию в качестве аргумента — эта функция должна вызывать динамическую функцию import() в своем теле.

React.Suspense позволяет нам указать резервную опору , которая принимает содержимое-заполнитель, которое будет использоваться в качестве индикатора загрузки во время загрузки всех ленивых компонентов.

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

Начнем

Предположим, у нас есть приложение React, и мы импортировали About компонент в файл Home:

import AboutUs from './About';

const Home = () => {
   return (
      <div className="App">
         <h1>Home Page</h1>
         <AboutUs />
      </div>
   );
};

export default Home;

Теперь мы можем реализовать lazy loading, используя React.lazy():

import React from 'react';

// Lazy loading 
const AboutUs = React.lazy(() => import('./About'));

const Home = () => {
   return (
      <div className="App">
         <h1>Home Page</h1>
         <AboutUs />
      </div>
   );
};
export default Home;
Примечание: React.lazy() при таком использовании возвращается Promise объект. Это обещание приводит к модулю, содержащему компонент React, который мы хотим отложенно загружать при его default экспорте.

Мы реализовали отложенную загрузку с помощью React.lazy(), но приведенный выше код всегда выдает ошибку , сообщающую, что наш “React component suspended while rendering, but no fallback UI was specified”. Это можно исправить, обернув компонент символами React.Suspense's fallbackz и прикрепив резервные props, как мы объясняли ранее:

import React from 'react';
const AboutUs = React.lazy(() => import('./About'));

const Home = () => {
   return (
      <div className="App">
         <h1>Home Page</h1>
         <React.Suspense fallback={<div>Loading...</div>}>
            <AboutUs />
         </React.Suspense>
      </div>
   );
};
export default Home;
Примечание. Резервная опора может использовать компонент, который будет отображаться до загрузки исходного контента.

Кроме того, мы можем решить деструктурировать импорт React, чтобы сделать код чище и читабельнее:

import { lazy, Suspense } from 'react';
const AboutUs = lazy(() => import('./About'));

const Home = () => {
   return (
      <div className="App">
         <h1>Home Page</h1>
         <Suspense fallback={<div>Loading...</div>}>
            <AboutUs />
         </Suspense>
      </div>
   );
};
export default Home;
До сих пор мы видели, как реализовать отложенную загрузку в наших импортированных компонентах. Теперь давайте посмотрим, как реализовать это в наших маршрутах при маршрутизации с помощью React Router.

Как реализовать lazy loading с помощью React Router

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

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

import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./Home'));
const Products = lazy(() => import('./Products'));

function App() {
   return (
      <BrowserRouter>
         <Suspense fallback={<div>Loading...</div>}>
            <Routes>
               <Route path="/" element={<Home />} />
               <Route path="/products" element={<Products />} />
            </Routes>
         </Suspense>
      </BrowserRouter>
   );
}
export default App;

Заключение

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