Описание: Ленивая загрузка (и предварительная загрузка) компонентов в React 16.6
В React 16.6 добавлена новая функция: React.lazy(), которая упрощает разделение кода.
Затем узнайте, как использовать новую функцию React.lazy, и поймите, почему вы должны использовать ее в стандартной демо-версии приложения.
Мы создали веб-приложение для акций, приложение показывает список некоторых акций, нажмите на одну из акций, она покажет недавний график тренда этой акции.
try itВыше перечислены все функции приложения. ты сможешьGithub RepoПрочитайте исходный код проекта (вы также можете пройти через PR, чтобы просмотреть изменения проекта и рабочие версии для каждого коммита).
В этой статье нас интересует толькоApp.js
Кодируйте логику внутри этого файла.
import React from "react";
import StockTable from "./StockTable";
import StockChart from "./StockChart";
class App extends React.Component {
state = {
selectedStock: null
};
render() {
const { stocks } = this.props;
const { selectedStock } = this.state;
return (
<React.Fragment>
<StockTable
stocks={stocks}
onSelect={selectedStock => this.setState({ selectedStock })}
/>
{selectedStock && (
<StockChart
stock={selectedStock}
onClose={() => this.setState({ selectedStock: false })}
/>
)}
</React.Fragment>
);
}
}
export default App;
App
Компонент получает данные номенклатуры и отображает<StockTable/>
компоненты. Когда одна из акций нажимается для выбора,App
покажет график для этой акции<StockChart>
В чем проблема?
мы хотимApp
Загружать и отображать как можно быстрее<StockTable />
, ноApp
Но подождите, пока браузер загрузится (распаковать, проанализировать, скомпилировать, выполнить и т. д.)StockChart
код.
Дисплей можно увидеть через Chrome DevTools<StockTable />
Запись прошедшего времени.
экспонатStockTable
Всего 2470 мс (имитация сетевой среды Fast3G и 4-ядерного обычного процессора)
На рисунке ниже видно, что входит в сжатый 125-килобайтный файл, передаваемый в браузер.
Как мы и ожидали, страница загружает реакции, реакции-дом и некоторые зависимости реакции, но страница также загружает зависимости моментов, лодаша и победы зависимостей компонентов. экспонат<StockTable />
Эти зависимости не являются обязательными.
Как загрузить зависимости
Ленивая загрузка компонентов
Используя «динамический импорт» веб-пакета, мы можем разделить связанный код на две части:main
Файл содержит то, что нужно отобразить<StockTable>
код и зависимости. Другой файл содержит отображение<StockChart />
код и зависимости.
dynamic import
Технология очень полезная, поэтому в версии React 16.6 добавлен новый API —React.lazy()
, что упрощает асинхронное обращение к компонентам React.
Для использования в App.jsReact.lazy()
, мы внесли два изменения в код.
Во-первых, код, который будет статически ссылаться на компонентimport StockChart from "./StockChart"
заменен вызовомReact.lazy()
,существуетlazy()
Пройти в анонимной функции в качестве параметра и динамически представить его в функцииStockChart
компоненты. Таким образом, браузер не загрузит компонент, пока мы его не отобразим../StockChart.js
файл и его зависимости.
Если React хочет отображать<StockChart />
Когда компонент установлен, что произойдет, если код, от которого зависит компонент, еще не загружен? Вот почему мы добавили<React.Suspense/>
. Он будет отображаться до тех пор, пока код не будет загруженfallback
Значение, переданное атрибутом props, будет отображать содержимое дочернего узла только после того, как будет готов весь код, от которого зависит дочерний узел.
СейчасApp
будет упакован в два файла.
main.js
Файл всего 36 КБ и содержит<StockChart />
И его зависимый кодовый файл 89KB.
После оптимизации, как показано на рисунке ниже, в браузере отображается<StockTable />
Необходимое время.
Браузеру потребовалось 760 мс для загрузкиmain.js
(ранее 1250 мс), а выполнение скрипта занимает 61 мс (ранее 487 мс).<StockTable />
Заняло всего 1546 мс (ранее 2460 мс).
Preloading — ленивая загрузка компонентов
Теперь мы ускорили загрузку приложения. Но есть еще одна проблема.
Когда пользователь щелкает элемент в первый раз, будут отображаться компоненты резервной схемы «Загрузка…». Это потому чтоApp
Нужно дождаться загрузки браузера<StockChart />
код.
Если мы хотим избежать отображения состояния загрузки, такого как «Загрузка...», нам нужно загрузить код до того, как пользователь щелкнет.
Простой способ реализовать предварительную загрузку кода — заранее вызвать React.lazy().
const stockChartPromise = import("./StockChart");
const StockChart = React.lazy(() => stockChartPromise);
когда мы звонимdynamic imoprt
, компонент начинает загружаться и не блокируется<StockTable />
Загрузка компонентов.
Взгляните на запись загрузки приложения и сравнение с немодифицированной версией.
Когда пользователь щелкнет элемент в течение 1 с, он увидит «Загрузка...».
Вы также можете оптимизировать ленивую функцию по-своему, чтобы сделать предварительную загрузку компонентов более общей и удобной.
function lazyWithPreload(factory) {
const Component = React.lazy(factory);
Component.preload = factory;
return Component;
}
const StockChart = lazyWithPreload(() => import("./StockChart"));
// somewhere in your component
...
handleYouMayNeedToRenderStockChartSoonEvent() {
StockChart.preload();
}
...
предварительно визуализированные компоненты
Вышеперечисленных функций уже достаточно для использования демонстрационного приложения. Но для более крупных проектов компонент может также иметь код или данные из других ленивых компонентов до того, как ленивый компонент будет загружен, поэтому пользователю все еще нужно время, чтобы дождаться загрузки компонента.
Еще один способ предварительной загрузки компонента — отрисовка его заранее. Отрисовка компонентов на странице, но не отображение их на странице, то есть скрытая отрисовка.
class App extends React.Component {
state = {
selectedStock: null
};
render() {
const { stocks } = this.props;
const { selectedStock } = this.state;
return (
<React.Suspense fallback={<div>Loading...</div>}>
<StockTable
stocks={stocks}
onSelect={selectedStock => this.setState({ selectedStock })}
/>
{selectedStock && (
<StockChart
stock={selectedStock}
onClose={() => this.setState({ selectedStock: false })}
/>
)}
{/* Preload <StockChart/> */}
<React.Suspense fallback={null}>
<div hidden={true}>
<StockChart stock={stocks[0]} />
</div>
</React.Suspense>
</React.Suspense>
);
}
}
React загрузится после первого рендеринга приложения.<Stockchart />
И попробуйте отрендерить компонент, чтобы также были загружены зависимости или код, необходимый компоненту.
мы будем懒加载组件
Завернутая в скрытый div, страница ничего не покажет после загрузки. а также используетсяReact.suspense
завернуть этоdiv
, и этоfallback
значениеnull
, поэтому он не отображается при загрузке.
Примечание:
hidden
Атрибут обычно указывает, что узел не имеет значения, и браузер не будет отображать элементы с этим атрибутом. React не выполняет никакой специальной обработки этого свойства (но может обрабатывать скрытые компоненты с более низким приоритетом в будущих версиях).
Что еще?
Последний метод доступен во многих сценариях, но все же имеет некоторые проблемы.
Во-первых, для лениво загруженных компонентов, которые отображаются скрытыми,hidden
Свойства не являются полностью допустимыми. Например, используйтеportalЛениво загруженные компоненты не будут скрыты (вы можете использовать портал, чтобы сделать это без дополнительного div, но это всего лишь хак, и он не будет использоваться в будущем).
Во-вторых, добавляются дополнительные узлы Dom, даже если узлы Dom были скрыты, что может стать проблемой производительности.
Лучший подход — указать React отображать ленивый компонент, но не добавлять его в дерево Dom после загрузки. Но, насколько я понимаю, в текущей версии React это невозможно.
Еще одно улучшение, которое мы можем сделать, — повторно использовать Dom, который мы подготовили при предварительном рендеринге, чтобы, когда пришло время рендерить компонент диаграммы, React не нужно было создавать его снова. Если пользователь собирается нажать на акцию, мы можем отобразить ее с правильными данными до того, как пользователь нажмет (так)
Это все для этой статьи, спасибо за чтение.
Технологический еженедельник IVWEBШок в сети, обратите внимание на публичный номер: сообщество IVWEB, регулярно каждую неделю публикуйте качественные статьи.
- Сборник статей еженедельника:weekly