Современные JavaScript приложения могут быть довольно большими с точки зрения размера bundle
пакета. Вам бы не хотелось, чтобы ваши пользователи загружали JavaScript пакет объемом в 1 МБ (ваш код и библиотеки, которые вы используете) только для загрузки первой страницы, верно? Но это то, что происходит по умолчанию, в современном веб-приложении, собраном с помощью Webpack.
Этот пакет будет содержать код, который может никогда и не запуститься, в случае если пользователь останется только на главной странице.
Разделение кода - это практика загрузки только того JavaScript-кода, который вам нужен в определенный момент времени и тогда, когда вам это нужно.
Это улучшает:
- производительность вашего приложения;
- влияние на память, и, следовательно, уменьшает использование батареи на мобильных устройствах;
- размер загруженного файла.
Lazy()
“Ленивая” (Lazy) функция - это функция, которая загружает компонент только в момент, когда он действительно понадобится, а не заранее при загрузке приложения. Это позволяет уменьшить время загрузки и ускорить отклик приложения.
Для создания ленивых компонентов используется функция lazy()
из пакета react
, которая принимает функцию-импорт компонента и возвращает новый компонент, который будет загружаться лениво.
Пример:
import React, { lazy, Suspense } from "react"
const MyLazyComponent = lazy(() => import("./MyComponent"))
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<MyLazyComponent />
</Suspense>
</div>
)
}
В этом примере мы создали компонент MyLazyComponent
, который будет загружаться лениво при его первом использовании на странице. Для загрузки компонента мы использовали функцию lazy()
и передали ей функцию-импорт компонента.
<Suspense />
Затем мы использовали компонент Suspense
для отображения заглушки (fallback) во время загрузки ленивого компонента. Заглушка может быть любым JSX-элементом, который будет отображаться во время загрузки компонента.
<Suspense>
позволяет отображать заглушки до тех пор, пока его дочерние элементы не закончат загрузку.
<Suspense fallback={<Loading />}>
<SomeComponent />
</Suspense>
props
children
: Фактический пользовательский интерфейс, который вы собираетесь рендерить. Еслиchildren
приостановится во время рендеринга, граница Suspense переключится на рендерингfallback
.fallback
: Альтернативный пользовательский интерфейс, который будет отображаться вместо реального пользовательского интерфейса, если он не закончил загрузку. Принимается любой допустимый узел React, хотя на практике запасной вариант - это легковесное представление-заполнитель, например, загрузочный спиннер или скелет. Приостановка будет автоматически переключаться наfallback
, когдаchildren
приостанавливает работу, и обратно наchildren
, когда данные будут готовы. Еслиfallback
приостанавливает работу во время рендеринга, он активирует ближайшую родительскую границу Suspense.
Ограничения
- React не сохраняет состояние для рендеров, которые были приостановлены до того, как они смогли смонтироваться в первый раз. Когда компонент загрузится, React повторит попытку рендеринга приостановленного дерева с нуля.
- Если
Suspense
отображал содержимое для дерева, но затем снова приостановился, тооткат
будет показан снова, если только обновление, вызвавшее его, не было вызваноstartTransition
илиuseDeferredValue
. - Если React необходимо скрыть уже видимый контент из-за повторного приостановления, он очистит layout Effects в дереве контента. Когда контент снова будет готов к показу, React снова запустит Эффекты компоновки. Это гарантирует, что Эффекты, измеряющие макет DOM, не попытаются сделать это, пока содержимое скрыто.
- React включает в себя такие “подкапотные” оптимизации, как Streaming Server Rendering и Selective Hydration, которые интегрированы в Suspense. Чтобы узнать больше, прочитайте архитектурный обзор и посмотрите технический доклад.