React 路由器基础代码拆分(获取第一个块,然后在后台异步获取其他块)

IT技术 reactjs create-react-app react-router-dom code-splitting code-splitting-async
2021-05-09 20:23:25

我正在使用create-react-app我想对路由器进行基本代码拆分,但我想获取用户在浏览器中打开的第一个块,然后在后台异步获取其他块

路线

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} />

假设,如果用户在浏览器中打开 /home 则在加载第一个块后首先加载 home 块,在后台异步调用其他块

所需输出

  1. /home在浏览器中打开
  2. 先拿回家块
  3. 然后其他三个块在后台异步

实际上我正在通过lighthouse chrome 扩展测试性能路由器基础代码拆分为我提供了第一页的良好性能,但是当我打开第二页时,它需要时间,但不应该需要时间。我认为如果我们在加载第一个块后在后台异步获取其他块是可能的

2个回答

您可以通过使用浏览器资源提示(预加载和预取)来实现这一点

如果您正在使用 webpack,那么魔术注释会很有帮助。你可以尝试这样的事情:

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'));

在上述情况下,无论url是什么,它都会预加载homemodule并预取其他三个低优先级的module。

如果你想要动态行为,你可以尝试使用插件:https : //github.com/SebastianS90/webpack-prefetch-chunk

添加插件后,您可以使用webpack_require .pfc 方法在后台加载块。

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;
  }
};

Suspense包裹路由器,它需要一个回退(在加载块时显示一些内容,如果它还没有加载)...

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>;
    
return (
  <Suspense fallback={<Loading/>}>
    <Router>
      <HomeModule path="/home" />
      <AuthModule path="/auth" />
      <ProfileModule path="/profile" />
      <MerchantModule path="/merchant" />
    </Router>
  </Suspense>
)