- PVSM.RU - https://www.pvsm.ru -
Этот code splitting, честное слово, уже немного надоел. Мы все ходим и ходим по кругу, и в этом и есть главная проблема.
Code splitting начинался как разделение на уровне Модулей, а закончился как разделение на уровне Компонент.
И проблема тут исключительно в голове — React.lazy это хорошо, но и import никуда не делся… Так почему же code splitting только про компоненты?
React.lazy, React-Loadable, Loadable-Components, Imported-component — на свете много библиотек, которые оборачивают загрузку модуля в некий сахар, исключительно чтобы немного более user-friendly обработать загрузку компонента и показать его по готовности. Минимальный код для «async-loader».
const loadable = (loaderFunction) =>
class AsyncComponent extends React.Component {
state = { ResultComponent: null, error: false, };
componentWillMount() {
loaderFunction
.then(result => this.setState({ ResultComponent: result.default || result})) // "es6" default export
.catch(() => this.setState({ error: true });
}
render() {
const { error, ResultComponent } = this.state;
// Display loaded component
return ResultComponent
? <ResultComponent {...this.props}/>
: (error ? <ErrorComponent /> : <LoadingComponent />)
}
}
Suspense и React.lazy просто другой вариант работы со стейтом. Ничего более.
Проблемы с этим вроде бы нет — import(«someStuff»).then('go-on'). Но тут опять начинаются вопросы про то как это правильно разместить в lifecycle Reactа, что делать есть промис заресолвился после смерти компонента, и так далее. И всех в голове одни компоненты.
Я провел мини опрос — НИКТО более не использует этот, самый древний, вариант code splitting. Не знает как его кушать в современных условиях. И в общем все плохо.
При этом решение есть, и опять же в 4 строчки — renderProps
Все очень просто — не смотря на то, что обьектом code splitting будет не Компонент а Модуль — местом совершения операции всеравно будет Компонент.
const loadableModule = (loaderFunction) =>
class AsyncComponent extends React.Component {
state = { ResultComponent: null, error: false, };
componentWillMount() {
loaderFunction
.then(result => this.setState({ module: result.default || result})) // "es6" default export
.catch(() => this.setState({ error: true });
}
render() {
const { error, module } = this.state;
return module
// pass it as a render prop!
? this.props.children(module)
// pass it as a render prop!
: (error ? <ErrorComponent /> : <LoadingComponent />)
}
}
Тот же самый паттерн, только повернутый в сторону загрузки кода и «предоставления» этого кода как renderProps.
import loadable from '@loadable/component'
const Moment = loadable.lib(() => import('moment'))
function FromNow({ date }) {
return (
<div>
<Moment fallback={date.toLocaleDateString()}>
{({ default: moment }) => moment(date).fromNow()}
</Moment>
</div>
)
}
import {importedLibraryDefault} from 'react-loadable-library';
const Moment = importedLibraryDefault( () => import('momentjs'));
<Moment>
{ (momentjs) => <span> {momentjs(date).format(FORMAT)}</span> }
</Moment>
// интерфейсно совместим с react-loadable-library, плюс поддержка Suspense
Дешево, и очень сердито. Мне это позволило срезать дополнительные 20%. Но, главное, позволило очень декларативно настроить code-splitting, который будет загружать только то, что надо, и когда надо.
Теперь твой ход, %username%.
И кто перепишет это на hooks?
Автор: Корзунов Антон
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/311092
Ссылки в тексте:
[1] loadable.lib: https://www.smooth-code.com/open-source/loadable-components/docs/library-splitting/
[2] react-loadable-library: https://github.com/theKashey/react-loadable-library
[3] react-imported-library: https://github.com/theKashey/react-imported-library
[4] Источник: https://habr.com/ru/post/443124/?utm_source=habrahabr&utm_medium=rss&utm_campaign=443124
Нажмите здесь для печати.