[Разработка веб-сайтов, JavaScript, ReactJS] 5 приемов по разделению «бандла» и «ленивой» загрузке компонентов в React (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Разделение Javascript-кода на несколько файлов называется разделением «бандла» или сборки (bundle splitting). Это позволяет загружать только тот код, который который используется приложением в данный момент, другие части загружаются по необходимости (по запросу пользователя).
Распространенные случаи разделения сборки и «ленивой» или отложенной загрузки (lazy loading) включают в себя следующее:
- Загрузка дополнительного кода при переходе пользователя к новому представлению (view — слой, отвечающий за визуальное отображение)
- Загрузка такого кода может быть связана с определенным действием, таким как прокрутка или нажатие кнопки
- Также можно реализовать предварительную загрузку определенных ресурсов, которые представляют потенциальный интерес для пользователя
- Это приводит к тому, что когда пользователь захочет получить доступ к определенной функциональности, она уже будет готова
1. Динамический импорт с помощью Webpack
Webpack позволяет загружать модули (компоненты) динамически во время выполнения кода. Рассмотрим пример:
import { useState } from 'react'
function MainComponent() {
const [isModalDisplayed, setModalDisplayed] = useState(false)
const [ModalComponent, setModalComponent] = useState(null)
const loadModalComponent = async () => {
const loadResult = await import('./components/Modal.js')
setModalComponent(() => loadResult.default)
}
return (
<div>
{isModalDisplayed && ModalComponent ? <ModalComponent /> : null}
<button
onClick={() => {
setModalDisplayed(true)
loadModalComponent()
}}
>
Load Modal Component
</button>
</div>
)
}
Динамический импорт может использоваться в любом месте кода. Такой импорт сообщает Webpack о необходимости создания отдельной сборки для конкретного компонента. Поскольку модальное окно отображается только когда пользователь нажимает кнопку, мы можем отложить загрузку соответствующего кода.
Динамический импорт позволяет каждому компоненту выступать в роли микрофронтенда (microfrontend).
2. Split API для загрузки React-компонентов
Пакет fusion-react предоставляет интерфейс split, компонент-обертку для отображения различных компонентов во время загрузки сборки:
- Резервного компонента при возникновении ошибки
- «Настоящего» компонента после загрузки сборки
Рассматриваемый интерфейс облегчает задачу разделения React-компонентов, позволяя избежать повторения шаблонного кода.
import { Link, Switch, Route } from 'react-router-dom'
import { split } from 'fusion-react'
const Loading = () => <div>Loading...</div>
const Error = () => <div>Error</div>
const Hello = split({
load: () => import('./components/hello.js'),
Loading,
Error,
})
const Root = () => (
<>
<div>
<ul>
<li>
<Link to='/'>Home</Link>
</li>
<li>
<Link to='/hello'>Hello</Link>
</li>
</ul>
</div>
<Switch>
<Route path='/' exact component={Home} />
<Route path='/hello' component={Hello} />
</Switch>
</>
)
Разделение компонентов верхнего уровня на основе маршрутов — еще одна техника оптимизации, способ уменьшения времени загрузки приложения.
В целом, отложенная загрузка кода до запроса пользователем страницы по конкретному маршруту — это хорошая идея.
Интерфейс split в приведенном примере откладывает загрузку компонента Hello до того момента, когда пользователь перейдет по соответствующему маршруту. Загружаемый компонент указывается в свойстве load.
В данном случае мы также имеем возможность использовать динамический импорт.
Прим. пер.: существуют более специализированные и популярные решения для ленивой загрузки React-компонентов, например, react-loadable или react-lazyload.
3. Создание «вендорного бандла» (vendor bundle)
Прежде всего, вы можете спросить, для чего нам это нужно? Основная идея заключается в том, что в вендор помещается (выносится) код, который изменяется намного реже, чем код разрабатываемого приложения. Это позволяет использовать эффективные техники по кэшированию кода для повышения скорости загрузки страниц.
Вот как можно извлечь вендорный бандл из директории node_modules:
const path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'src/index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
},
}
Если после этого вы запустите сборку (yarn build или npm run build), то увидите что-то вроде этого:
⬡ webpack: Build Finished
⬡ webpack: assets by status 128 KiB [emitted]
asset 935.js 124 KiB [emitted] [minimized] (id hint: vendors) 2 related assets
asset main.js 3.24 KiB [emitted] [minimized] (name: main) 1 related asset
asset index.html 267 bytes [emitted]
assets by status 7.9 KiB [compared for emit]
asset main.css 7.72 KiB [compared for emit] (name: main) 1 related asset
asset 34.js 187 bytes [compared for emit] [minimized] 1 related asset
Entrypoint main 135 KiB (326 KiB) = 935.js 124 KiB main.css 7.72 KiB main.js 3.34 KiB 3 auxiliary assets
...
webpack 5.5.0 compiled successfully in 4856 ms
4. Создание нескольких вендорных бандлов
Обычно, все модули объединяются в один вендорный бандл.
Знаете ли вы, что мы можем создать несколько таких бандлов?
Например, поскольку React не будет меняться между сборками, имеет смысл закэшировать его в виде отдельного пакета в случаях, когда вопрос производительности является критически важным.
Файл с настройками Webpack принимает свойство optimization, позволяющее разделять вендорный бандл:
module.exports = {
splitChunks: {
chunks: 'async',
cacheGroups: {
default: {
minChunks: 2,
reuseExistingChunk: true,
},
vendor_react: {
test: /.*\/node_modules\/react\/index\.js/,
name: 'vendor-react',
chunks: 'initial',
enforce: true,
},
},
},
}
После этого вендорный бандл будет разделен на client-vendor.js и clietn-vendor-react.js.
5. Ленивая загрузка компонентов с помощью React.lazy()
React.lazy() — это функция, позволяющая рендерить динамически импортируемые компоненты как обычные компоненты.
Обычный импорт:
import MyComponent from './MyComponent'
Динамический импорт с помощью React.lazy():
const OtherComponent = React.lazy(() => import('./OtherComponent')
Компоненты, загружаемые с помощью React.lazy(), должны быть обернуты в компонент Suspense, который позволяет отображать резервный контент (например, индикатор загрузки) до полной загрузки импортируемого компонента:
import { lazy, Suspense } from 'react'
const OtherComponent = lazy(() => import('./OtherComponent'))
function MyComponent() {
return (
<>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</>
)
}
Проп fallback принимает любой элемент (компонент). Компонент Suspense может быть помещен на любом родительском по отношению к «ленивому» компоненту уровне.
Suspense может оборачивать как отдельный компонент, так и группу компонентов:
import { lazy, Suspense } from 'react'
const OtherComponent = lazy(() => import('./OtherComponent'))
const AnotherComponent = lazy(() => import('./AnotherComponent'))
function MyComponent() {
return (
<>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</>
)
}
Заключение
После применения техник, названных в данной статье, при анализе производительности вашего приложения, вы увидите два главных улучшения. Уменьшение размера сборки, загружаемой при инициализации приложения, и увеличение количества сборок, загружаемых по необходимости.
Это, безусловно, положительно повлияет на пользовательский опыт работы с приложением, поскольку оно станет более быстрым и отзывчивым.
Также не стоит забывать о том, что загруженный JavaScript-код, должен быть разобран и выполнен, что также требует некоторого времени и вычислительной мощности.
Облачные серверы от Маклауд быстрые и безопасные.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
оригинал
===========
Источник:
habr.com
===========
===========
Автор оригинала: Minura Samaranayake
===========Похожие новости:
- [Разработка веб-сайтов, API] Как написать удобный API — 10 рекомендаций
- [JavaScript, Разработка мобильных приложений, Swift, ReactJS] Как Лёня с React на Swift переезжал
- [DIY или Сделай сам, Лайфхаки для гиков] Как собрать свой собственный прибор ночного видения за $50 из смартфона
- [Исследования и прогнозы в IT, Управление персоналом, Карьера в IT-индустрии] Когда уходят на покой программисты? 35 — это конец карьеры? (перевод)
- [Беспроводные технологии, Разработка на Raspberry Pi, Сетевое оборудование, DIY или Сделай сам] Превращаем одноплатник Cubietruck в Wi-Fi Hotspot с Captive portal, VPN-шлюзом и Ad block
- [Научно-популярное, Транспорт] История нефтеперевозок. От танкеров с бакинской нефтью до современных монстров
- [Разработка веб-сайтов, JavaScript, Программирование, GitHub, Игры и игровые приставки] Разработчик сделал Doom Captcha — теперь можно проходить тест на робота играя
- [Разработка веб-сайтов, Проектирование и рефакторинг, Хранение данных] Может поменять способ хранения?
- [Разработка веб-сайтов, Разработка мобильных приложений, Карьера в IT-индустрии] Без тимлида не обойтись, а что насчет техлида?
- [Бизнес-модели, IT-компании] Apple превращается в ещё одну Microsoft (перевод)
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_javascript, #_reactjs, #_javascript, #_razrabotka_sajtov (разработка сайтов), #_vds, #_vps, #_bystryj_vds (быстрый vds), #_deshevyj_vds (дешевый vds), #_blog_kompanii_maklaud (
Блог компании Маклауд
), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_javascript, #_reactjs
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:25
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Разделение Javascript-кода на несколько файлов называется разделением «бандла» или сборки (bundle splitting). Это позволяет загружать только тот код, который который используется приложением в данный момент, другие части загружаются по необходимости (по запросу пользователя). Распространенные случаи разделения сборки и «ленивой» или отложенной загрузки (lazy loading) включают в себя следующее:
Webpack позволяет загружать модули (компоненты) динамически во время выполнения кода. Рассмотрим пример: import { useState } from 'react'
function MainComponent() { const [isModalDisplayed, setModalDisplayed] = useState(false) const [ModalComponent, setModalComponent] = useState(null) const loadModalComponent = async () => { const loadResult = await import('./components/Modal.js') setModalComponent(() => loadResult.default) } return ( <div> {isModalDisplayed && ModalComponent ? <ModalComponent /> : null} <button onClick={() => { setModalDisplayed(true) loadModalComponent() }} > Load Modal Component </button> </div> ) } Динамический импорт может использоваться в любом месте кода. Такой импорт сообщает Webpack о необходимости создания отдельной сборки для конкретного компонента. Поскольку модальное окно отображается только когда пользователь нажимает кнопку, мы можем отложить загрузку соответствующего кода. Динамический импорт позволяет каждому компоненту выступать в роли микрофронтенда (microfrontend). 2. Split API для загрузки React-компонентов Пакет fusion-react предоставляет интерфейс split, компонент-обертку для отображения различных компонентов во время загрузки сборки:
Рассматриваемый интерфейс облегчает задачу разделения React-компонентов, позволяя избежать повторения шаблонного кода. import { Link, Switch, Route } from 'react-router-dom'
import { split } from 'fusion-react' const Loading = () => <div>Loading...</div> const Error = () => <div>Error</div> const Hello = split({ load: () => import('./components/hello.js'), Loading, Error, }) const Root = () => ( <> <div> <ul> <li> <Link to='/'>Home</Link> </li> <li> <Link to='/hello'>Hello</Link> </li> </ul> </div> <Switch> <Route path='/' exact component={Home} /> <Route path='/hello' component={Hello} /> </Switch> </> ) Разделение компонентов верхнего уровня на основе маршрутов — еще одна техника оптимизации, способ уменьшения времени загрузки приложения. В целом, отложенная загрузка кода до запроса пользователем страницы по конкретному маршруту — это хорошая идея. Интерфейс split в приведенном примере откладывает загрузку компонента Hello до того момента, когда пользователь перейдет по соответствующему маршруту. Загружаемый компонент указывается в свойстве load. В данном случае мы также имеем возможность использовать динамический импорт. Прим. пер.: существуют более специализированные и популярные решения для ленивой загрузки React-компонентов, например, react-loadable или react-lazyload. 3. Создание «вендорного бандла» (vendor bundle) Прежде всего, вы можете спросить, для чего нам это нужно? Основная идея заключается в том, что в вендор помещается (выносится) код, который изменяется намного реже, чем код разрабатываемого приложения. Это позволяет использовать эффективные техники по кэшированию кода для повышения скорости загрузки страниц. Вот как можно извлечь вендорный бандл из директории node_modules: const path = require('path')
module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[contenthash].js', }, } Если после этого вы запустите сборку (yarn build или npm run build), то увидите что-то вроде этого: ⬡ webpack: Build Finished
⬡ webpack: assets by status 128 KiB [emitted] asset 935.js 124 KiB [emitted] [minimized] (id hint: vendors) 2 related assets asset main.js 3.24 KiB [emitted] [minimized] (name: main) 1 related asset asset index.html 267 bytes [emitted] assets by status 7.9 KiB [compared for emit] asset main.css 7.72 KiB [compared for emit] (name: main) 1 related asset asset 34.js 187 bytes [compared for emit] [minimized] 1 related asset Entrypoint main 135 KiB (326 KiB) = 935.js 124 KiB main.css 7.72 KiB main.js 3.34 KiB 3 auxiliary assets ... webpack 5.5.0 compiled successfully in 4856 ms 4. Создание нескольких вендорных бандлов Обычно, все модули объединяются в один вендорный бандл. Знаете ли вы, что мы можем создать несколько таких бандлов? Например, поскольку React не будет меняться между сборками, имеет смысл закэшировать его в виде отдельного пакета в случаях, когда вопрос производительности является критически важным. Файл с настройками Webpack принимает свойство optimization, позволяющее разделять вендорный бандл: module.exports = {
splitChunks: { chunks: 'async', cacheGroups: { default: { minChunks: 2, reuseExistingChunk: true, }, vendor_react: { test: /.*\/node_modules\/react\/index\.js/, name: 'vendor-react', chunks: 'initial', enforce: true, }, }, }, } После этого вендорный бандл будет разделен на client-vendor.js и clietn-vendor-react.js. 5. Ленивая загрузка компонентов с помощью React.lazy() React.lazy() — это функция, позволяющая рендерить динамически импортируемые компоненты как обычные компоненты. Обычный импорт: import MyComponent from './MyComponent'
Динамический импорт с помощью React.lazy(): const OtherComponent = React.lazy(() => import('./OtherComponent')
Компоненты, загружаемые с помощью React.lazy(), должны быть обернуты в компонент Suspense, который позволяет отображать резервный контент (например, индикатор загрузки) до полной загрузки импортируемого компонента: import { lazy, Suspense } from 'react'
const OtherComponent = lazy(() => import('./OtherComponent')) function MyComponent() { return ( <> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </> ) } Проп fallback принимает любой элемент (компонент). Компонент Suspense может быть помещен на любом родительском по отношению к «ленивому» компоненту уровне. Suspense может оборачивать как отдельный компонент, так и группу компонентов: import { lazy, Suspense } from 'react'
const OtherComponent = lazy(() => import('./OtherComponent')) const AnotherComponent = lazy(() => import('./AnotherComponent')) function MyComponent() { return ( <> <Suspense fallback={<div>Loading...</div>}> <section> <OtherComponent /> <AnotherComponent /> </section> </Suspense> </> ) } Заключение После применения техник, названных в данной статье, при анализе производительности вашего приложения, вы увидите два главных улучшения. Уменьшение размера сборки, загружаемой при инициализации приложения, и увеличение количества сборок, загружаемых по необходимости. Это, безусловно, положительно повлияет на пользовательский опыт работы с приложением, поскольку оно станет более быстрым и отзывчивым. Также не стоит забывать о том, что загруженный JavaScript-код, должен быть разобран и выполнен, что также требует некоторого времени и вычислительной мощности. Облачные серверы от Маклауд быстрые и безопасные. Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации! оригинал =========== Источник: habr.com =========== =========== Автор оригинала: Minura Samaranayake ===========Похожие новости:
Блог компании Маклауд ), #_razrabotka_vebsajtov ( Разработка веб-сайтов ), #_javascript, #_reactjs |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:25
Часовой пояс: UTC + 5