您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
前言
对于页面性能优化,组件懒加载是个比较不错的方案,并且在整个项目打包后,如果未做代码分割,构建出的文件体积会非常大,也会出现比较常见的"访问项目某一页面,需要请求整个项目所有页面的资源"问题。
接下来讲一下在React
中懒加载我们的组件。
Suspense和Lazy
何时使用lazy函数,比如某个体积相对比较大的第三方库或插件(比如JS版的PDF预览库)只在单页应用(SPA)的某一个不是首页的页面使用了,这种情况就可以考虑代码分割,增加首屏的加载速度。
lazy函数可以单独使用,但是在加载组件时候,页面可能会出现空白,此时需要添加loading,这时就需要Suspense
了,代码如下:
const Foo = React.lazy(() => import('../componets/Foo));
<Foo />
上面的代码直接在函数中使用Foo
组件页面加载时会出现白屏,所以需要Suspense
来包裹,代码如下:
const Foo = React.lazy(() => import('../componets/Foo));
<React.Suspense fallback={
<div>loading...</div>}>
<Foo/>
</React.Suspense>
上述为基本使用,对于在当前页面想要懒加载其他组件的情况可以这样做:
import {
Spin } from 'antd';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={
<Spin />}>
<OtherComponent />
</Suspense>
</div>
);
}
OtherComponent
是通过懒加载加载进来的,所以渲染页面的时候可能会有延迟,但使用了Suspense
之后,可优化交互。在<OtherComponent />
外面使用Suspense
标签,并在fallback
中声明OtherComponent
加载完成前做的事,即可优化整个页面的交互
fallback
属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense
组件置于懒加载组件之上的任何位置。你甚至可以用一个 Suspense
组件包裹多个懒加载组件。
import {
Spin } from 'antd';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={
<Spin />}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
);
}
在Ice.js项目中实践
在Ice
项目中,如果想要对整个项目中所有页面进行页面级组件懒加载(代码分割),可以这样:
- 在
app.tsx
中配置fallback
,对应Suspense
中的fallback
:
import {
Spin } from 'antd';
const appConfig: IAppConfig = {
app: {
rootId: 'ice-container',
},
router: {
fallback: <Spin />,
type: 'browser',
},
};
runApp(appConfig);
- 在路由文件中使用懒加载的形式引入组件:
import {
lazy, IRouterConfig } from 'ice';
import Layout from '@/layouts/BasicLayout';
const Home = lazy(() => import('@/pages/Home'));
const routes: IRouterConfig[] = [
{
path: '/',
component: Layout,
children: [
{
path: '/home',
component: Home,
},
],
},
];
export default routes;
- 在
build.json
中配置懒加载模式构建,这样构建出来的产物会有多个javascript
文件,实现代码分割:
{
// ...
"router": {
"lazy": true
}
}
这样,就实现了代码分割的效果啦~如图: