在通常的react項目中在性能優化方面除了減小各類靜態資源的體積外,還有一個效果顯著的方式,異步加載組件,包括頁面級組件(在路由中配置的),以及其餘的體積較大的第三方組件(bizcharts,bScroll,...),本文會詳細說明使用react-loaable來實現三種異步組件:javascript
項目中安裝 react-loadble ,babel插件安裝 syntax-dynamic-import. react-loadable是經過webpack的異步import實現的 若是要實現非頁面的組件加載,首先要在webpack配置中將相應的代碼塊分離出來,splitchunk!!! (例如,bizcharts 等代碼庫,須要在splitchunk中給個單獨配置)java
如今咱們來說list頁面實現異步組件,其中在Loadable方法的參數配置中,react
import Loadable from 'react-loadable';
// 首次加載
const Loading = ({ isLoading, error }) => {
if (isLoading) {
return <div>加載中...</div>;
} else if (error) {
return <div>頁面加載出現問題, 請刷新後重試</div>;
}
return null;
};
const AsyncList = Loadable({
loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
loading: Loading
});
複製代碼
const A = Loadable({
loader,
render: (loaded, props) => {
const CurComponent = 條件?loaded.default : loaded.other
return <CurComponent {...props} />;
},
loading,
});
<A in={true} />
複製代碼
此時props就是{in:tue}webpack
未使用react-loadable以前的頁面,以下:web
// 首次加載
import Index from '@pages/index';
import List from '@pages/list';
const Routes = () => (
<Router history={history}>
<Route exact path="/index" component={Index} />
<Route exact path="/list" component={List} />
</Router>
);
複製代碼
如今咱們來說list頁面實現異步組件,其中在Loadable方法的參數配置中,能夠根據項目須要修改loading中的過渡效果性能優化
import Loadable from 'react-loadable';
// 首次加載
import Index from '@pages/index';
const Loading = ({ isLoading, error }) => {
if (isLoading) {
return <div>加載中...</div>;
} else if (error) {
return <div>頁面加載出現問題, 請刷新後重試</div>;
}
return null;
};
const AsyncList = Loadable({
loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
loading: Loading
});
const Routes = () => (
<Router history={history}>
<Route exact path="/index" component={Index} />
<Route exact path="/list" component={AsyncList} />
</Router>
複製代碼
若是加載的js是個組件的集合,例如components.jsx 文件bash
export A =()=>{<div>A</div>};
export B =()=>{<div>B</div>};
export C =()=>{<div>C</div>};
複製代碼
此時要加載A頁面,須要在render函數中的loaded參數得到A屬性即A組件babel
const AsyncA = Loadable({
loader: () => import(/* webpackChunkName: 'page_list' */'@pages/list'),
render: (loaded, props) => {
const CurComponent = loaded.A; // A組件
return <CurComponent {...props} />;
},
loading: Loading
});
複製代碼
普通的react組件的加載相似普通的頁面的加載異步
import React from 'react';
import { Chart, Geom, Axis, Tooltip, Label, Guide, } from 'bizcharts';
class Index extends React.Component {
render()
return (
<div>
<Chart data={data} scale={scale} className="chart" forceFit >
<Axis name="score" />
<Axis name="number" />
<Tooltip triggerOn="none"/>
<Geom type="interval" position="score*number" ></Geom>
</Chart>
</div>
);
}
}
export default Index;
複製代碼
先寫一個通用的異步加載chart的函數getBizcharts,loading和上文提到的同樣,函數的參數ReactComponent 就是原來的chartA,chartB組件 render 函數中的loader就是bizchart對象,經過getBizcharts函數就能夠在chartA的組件的props.bizchart中獲取和原來同樣的bizcharts組件。ide
import Loadable from 'react-loadable';
export const getBizcharts = (ReactComponent) => Loadable({
loader: () => import(/* webpackChunkName: "bizcharts" */'bizcharts'),
render: (loaded, props) => <ReactComponent bizchart={loaded} {...props} />,
loading: Loading
});
複製代碼
這事圖表組件的樣子:
import React from 'react';
import { getBizcharts } from '@components/getAsyncComponent';
// import { Chart, Geom, Axis, Tooltip, Label, Guide, } from 'bizcharts';
class Index extends React.Component {
render()
const {
Chart, Geom, Axis, Tooltip, Label, Guide,
} = this.props.bizchart;
return (
<div>
<Chart data={data} scale={scale} className="chart" forceFit >
<Axis name="score" />
<Axis name="number" />
<Tooltip triggerOn="none"/>
<Geom type="interval" position="score*number" ></Geom>
</Chart>
</div>
);
}
}
export default getBizcharts(Index);
複製代碼
在render中經過props.bizchart獲取bizchart組件,導出時調用getBizcharts方法
若是該類組件的export 是一個單獨的構造,就是在render的時候出入 loaded.default 若是是一個集合,能夠直接出入,在使用的組件中獲取