code-splite有两种实现方式:
- 基于组件的code spliting
- 基于路由的code spliting
一个路由对应的其实就是一个组件,并没有什么特别,如果是基于路由的code spliting,那么切分的粒度会是路由级别的。
如果基于组件的code spliting,那么切分的粒度是组件级的,也就是说基于组件的代码分割粒度更细,可以对Modal、tabs以及其他的UI 组件都进行代码分割
基于组件的code spliting 相比于 基于路由的code spliting 的另一个好处是性能更好。
考虑以下场景:
- 页面中有一个选项卡中隐藏了一个地图组件,当用户没有点击该选项卡,不需要加载这个巨大的地图组件
- 对于一些可以推迟加载的内容,不需要和高优先级的组件同时加载,例如:在页面底部的内容组件,它们不需要和顶部的组件同时加载,可以推迟到页面展示这些组件时才进行加载
react-loadable使用基于组件的code spliting 更容易实现,总的来说,react-loadable是一个用于动态加载组件的库,虽然,可以使用es6的 dynamic import 来实现动态加载组件,但是使用react-loadable可以做的更好,提供了更加丰富以及贴近业务的特性,如:
- 加载失败的处理
- 加载超时的处理
- 加载中的状态处理,常见的有在加载中时,展示一个loading
- 延迟展示加载中的状态
- 服务端的处理方式
因此,使用react-loadable作为动态加载组件更合适
loading组件定义:
import Loadable from 'react-loadable';
import Spin from './components/spin';
import React, { Component } from 'react';
export const Loading = props => {
if (props.error) {
// props.retry&&props.retry();
!__LOCAL__&&window.location.reload();
// eslint-disable-next-line no-console
console.log(props.error)
return <div >加载失败</div>
} else if (props.timedOut) {
// props.retry&&props.retry();
!__LOCAL__&&window.location.reload();
return <div >加载超时</div>
} else if (props.pastDelay) {
return <Spin />
}
return null
};
export const importPath = ({loader}) => {
return Loadable({
loader,
loading:Loading,
delay: 200,
timeout: 200000,
})
}
与react-router配合:
import { importPath } from './loadable';
let router = [
{
path: '/',
exact: true,
component:importPath({
loader: () => import(/* webpackChunkName:"home" */ "pages/home.tsx"),
}),
},
{
path: '/order',
exact: true,
component:importPath({
loader: () => import(/* webpackChunkName:"" */ "pages/order"),
}),
}
]