基于路由的代码分割及其异常
官网介绍了基于路由的代码分割:
https://zh-hans.reactjs.org/docs/code-splitting.html#route-based-code-splitting
不过有一个异常, babel-loader的预设@babel/react
会导致不生成异步入口点文件:
import('!babel-loader?presets[]=@babel/env&presets[]=@babel/react!.').then(expo => {
console.log(expo); // 代码是内联打包的, 不生成文件?!
});
解决办法: 使用lazy组件
lazy组件是指lazy()
函数返回的组件, 用于延迟加载其它组件, 配合Suspense
组件使用.
router.js
:
import { lazy } from "react";
const Pages = [ 'Keyframes', 'WhatsJSX', 'useHistory', 'AsyncImport', 'font', 'FunctionComponent' ];
// const ReactPages = Pages.map(page => require(`@/pages/${page}`).default); // 臃肿的index.js
// 页面全部映射为lazy组件, 在Route中配置Suspense子组件, 并设置该Suspense组件的fallback和children属性
// Suspense组件的children属性就是延迟加载的页面组件
// 这些延迟加载的页面组件必须是函数或者类
const ReactPages = Pages.map(page => lazy(() => import(
/* webpackChunkName: "page" */
`@/pages/${page}`
)));
export { Pages, ReactPages };
index.js
:
import { Pages, ReactPages, } from '@/pages/router';
import { HashRouter as Router, Switch, Route, Link, useHistory, } from 'react-router-dom';
const map_route = ReactPages.map((LazyComponent, index) => (
<Route key={index} path={'/' + Pages[index]}>
{
// 如果Route的children是一个函数, 则可以接受route参数
route => {
return (
// <Suspense fallback={<h1>加载中...</h1>}>
<Suspense fallback={<Loadding />}>
{/* LazyComponent是lazy函数返回的组件 */}
<LazyComponent></LazyComponent>
</Suspense>
);
}
}
</Route>
));
// 由于App不是一个通用组件, 不需要继承Component类, 直接导出一个React组件即可
export default (
<Router>
<div className={css.app}>
<Header />
<div>
<Switch>
{map_route}
<Route path="/">{Index}</Route>
</Switch>
</div>
</div>
</Router>
);