В настоящее время я использую React 16 с Suspense и Lazy для разделения кода моей кодовой базы. Хотя хотелось бы предзагрузить компоненты.
В моем примере ниже у меня есть два маршрута. Есть ли способ предварительно загрузить Demo сразу после монтирования Prime? Я попытался создать еще один динамический импорт в componentDidMount страницы Prime, но React.lazy, похоже, не может получить тот же файл, что и динамический импорт ниже.
import React, { lazy, Suspense } from 'react';
import { Switch, Route, withRouter } from 'react-router-dom';
import GlobalStyle from 'styles';
import Loading from 'common/Loading';
const Prime = lazy(() => import(/* webpackChunkName: "Prime" */'modules/Prime'));
const Demo = lazy(() => import(/* webpackChunkName: "Demo" */'modules/Demo'));
const App = () => (
<main>
<GlobalStyle />
<Suspense fallback = {<Loading>Loading...</Loading>}>
<Switch>
<Route path = "/" component = {Prime} exact />
<Route path = "/demo" component = {Demo} />
</Switch>
</Suspense>
</main>
);
export default withRouter(App);
Итак, я пробовал разные подходы, например, с webpackChunkName и без него, а также различные способы импорта другого компонента в componentDidMount, как показано ниже. Первые два подхода к импорту файла в componentDidMount привели к ошибке Webpack, показанной внизу изображения ниже. Только третий продолжил работу, но сделал файл 2.[hash].js в образе, загружаемый только после посещения страницы, а не на componentDidMount
Что мне здесь не хватает?
Код modules/Demo.jsx:
import React from 'react';
import LogoIcon from 'vectors/logo.svg';
import PageLink from 'common/PageLink';
import Anchor from 'common/Anchor';
import CenteredSection from 'common/CenteredSection';
const Demo = () => (
<CenteredSection variant = "green">
<LogoIcon />
<PageLink to = "/" variant = "green">Go to home page</PageLink>
</CenteredSection>
);
export default Demo;
@RyanC благодарит за ответ. Я добавил код демонстрационной страницы. Вы также можете просмотреть кодовую базу здесь: github.com/JBostelaar/react-prime/tree/progressive-web-app/s rc Я тоже думал, что первый подход не сработает, но все же я хотел показать, что я пробовал. 2 выдает ошибку, 3 не загружает страницу предварительно.
Структура кода немного отличается от того, что я ожидал. Я ожидал увидеть modules/Demo.jsx и modules/Prime.jsx. Я не говорю, что то, что у вас есть, «неправильно», но наличие Demo/index.jsx вместо этого просто отклоняется от подходов, которые я использовал, и я могу дать более уверенное направление.
Спасибо за ваш вклад, но я почти уверен, что проблема не в структуре моих папок или именовании.
Хорошее использование webpackChunkName. Не знал, что можно так называть свои куски, спасибо;)





Не уверен, насколько это поможет, но вот песочница кода, который работает (демонстрация загружается с помощью componentDidMount). Это значительно упрощенная версия вашего кода, использующая приложение create-response-app для config. Возможно, вы можете взять это за отправную точку и постепенно преобразовать ее ближе к своему приложению, чтобы увидеть, из-за чего динамический импорт больше не работает должным образом.
Это невероятно легко сделать, я думаю, что существует неправильное понимание того, что делают lazy () и Suspense под капотом.
Единственное ожидание, которое имеет React.lazy (), - это то, что он принимает функцию, которая возвращает обещание, которое разрешается с помощью компонента по умолчанию.
React.lazy(() => Promise<{default: MyComponent}>)
Поэтому, если вы хотите выполнить предварительную загрузку, все, что вам нужно сделать, это выполнить обещание заранее.
// So change this, which will NOT preload
import React from 'react';
const MyLazyComp = React.lazy(() => import('./path/to/component'));
/*********************************************/
// To this, which WILL preload
import React from 'react';
// kicks off immediately when the current file is imported
const componentPromise = import('./path/to/component');
// by the time this gets rendered, your component is probably already loaded
// Suspense still works exactly the same with this.
const MyLazyComp = React.lazy(() => componentPromise);
Тот факт, что это известная сигнатура, делает ее полезной во многих других ситуациях. Например, у меня есть несколько компонентов, которые полагаются на динамическую загрузку api карт Google, я смог создать функцию, которая загружает api карт Google, а затем импортирует компонент. Я не буду подробно останавливаться на деталях этого примера, поскольку он является касательным, но дело в том, что я сделал себе функцию, которая выполняет кучу асинхронных операций, а затем возвращает Promise с объектом {default: Component}.
import React from 'react';
const MyLazyComp = React.lazy(() => importMapsComponent('./path/to/comp'));
Использование
lazyв componentDidMount of Prime не принесет вам никакой пользы для случая предварительной загрузки, поскольку оно вызывает загрузку компонента при его рендеринге. Подходы 2 и 3 на первый взгляд кажутся хорошими, но ошибка, которую вы получаете для 1 и 2, заставляет меня хотеть увидеть код дляmodules/Demo, поскольку кажется, что что-то вызывает циклическую зависимость.