问题
I am using create-react-app. I want to react-router base code-splitting but I want to get the first chunk which user open in browser and then get other chunks asynchronously in the background
Routes
const HomeModule = React.lazy(() => import('./modules/ft_home_module/src/main'));
const AuthModule = React.lazy(() => import('./modules/ft_auth_module/src/main'));
const ProfileModule = React.lazy(() => import('./modules/ft_profile_module/src/main'));
const MerchantModule = React.lazy(() => import('./modules/ft_merchant_module/src/main'));
<Route path="/home" component={HomeModule} />
<Route path="/auth" component={AuthModule} />
<Route path="/profile" component={ProfileModule} />
<Route path="/merchant" component={MerchantModule} />
suppose, if user open /home in the browser then home chunk will be loaded first after loading first chunk call other chunks asynchronously in the background
Required Output
- Open
/home
in browser - Get home chunk first
- then other three chunks asynchronously in the background
actually I am testing performance through lighthouse chrome extension. router base code-splitting gives me the good performance of the first page but when I open second page it takes time but it should not take time. I think it is possible if we get other chunks async in the background after loading first chunk
回答1:
You can achieve this by using browser resource hints(Preload and prefetch)
If you are using webpack, then magic comments will be helpful. you can try something like this:
const HomeModule = React.lazy(() => import(/* webpackPreload: true * /'./modules/ft_home_module/src/main'));
const AuthModule = React.lazy(() => import(/* webpackPrefetch: true * /'./modules/ft_auth_module/src/main'));
const ProfileModule = React.lazy(() => import(/* webpackPrefetch: true * /'./modules/ft_profile_module/src/main'));
const MerchantModule = React.lazy(() => import(/* webpackPrefetch: true */ './modules/ft_merchant_module/src/main'));
In the above case, no matter what the url is it will preload the homemodule and prefetch the other three modules with low priority.
If you want the dynamic behaviour, you can try using the plugin: https://github.com/SebastianS90/webpack-prefetch-chunk
After adding the plugin, you can use webpack_require.pfc method to load the chunks in background.
const prefetchChunk = chunkName => {
if (!window.requestIdleCallback) {
return;
} else if (chunkName) {
let chunkArray = [].concat(chunkName);
window.requestIdleCallback(() => {
chunkArray.forEach(chunk => {
__webpack_require__.pfc(chunk);
});
});
} else {
return;
}
};
回答2:
Wrap the Router with Suspense that takes a fallback(show some content while loading chunk, if it was not yet loaded)...
import React,{Suspense} from 'react';
import {Router} from '@reach/router';
const HomeModule = React.lazy(() => import('./modules/ft_home_module/src/main'));
const AuthModule = React.lazy(() => import('./modules/ft_auth_module/src/main')) const ProfileModule = React.lazy(() => import('./modules/ft_profile_module/src/main'));
const MerchantModule = React.lazy(() => import('./modules/ft_merchant_module/src/main'));
const Loading = () => <div>Loading chunk..</div>
<Suspense fallback={<Loading/>}>
<Router>
<HomeModule path="/home" />
<AuthModule path="/auth" />
<ProfileModule path="/profile" />
<MerchantModule path="/merchant" />
</Router>
</Suspense>
来源:https://stackoverflow.com/questions/61931283/react-router-base-code-splitting-get-first-chunk-and-then-get-other-chunks-asyn