最近在網上也看到了react-router4的好多種按需加載的方法。react
傳送門:https://blog.csdn.net/foralienzhou/article/details/73437057npm
雖然本身的項目不大,可是也要區分前臺和後臺,若是讓訪問前臺的用戶也加載了後臺的js代碼,仍是很影響體驗的,因此挑了一種按需加載的方法進行實踐(基於create-react-app和Bundle組件)。bash
這裏的import不一樣於模塊引入時的import,能夠理解爲一個動態加載的模塊的函數(function-like),傳入其中的參數就是相應的模塊。例如對於原有的模塊引入import react from 'react'能夠寫爲import('react')。可是須要注意的是,import()會返回一個Promise對象。所以,能夠經過以下方式使用:網絡
btn.addEventListener('click', e => {
// 在這裏加載chat組件相關資源 chat.js
import('/components/chart').then(mod => {
someOperate(mod);
});
});
複製代碼
能夠看到,使用方式很是簡單,和平時咱們使用的Promise並無區別。固然,也能夠再加入一些異常處理:antd
btn.addEventListener('click', e => {
import('/components/chart').then(mod => {
someOperate(mod);
}).catch(err => {
console.log('failed');
});
});
複製代碼
咱們首先須要一個異步加載的包裝組件Bundle。Bundle的主要功能就是接收一個組件異步加載的方法,並返回相應的react組件。react-router
import React from 'react';
export default class Bundle extends React.Component {
constructor(props) {
super(props);
this.state = {
mod: null
};
}
componentWillMount() {
this.load(this.props)
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps)
}
}
load(props) {
this.setState({
mod: null
});
props.load().then((mod) => {
this.setState({
mod: mod.default ? mod.default : mod
});
});
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
複製代碼
引入模塊的時候須要用Bundle組件包一下app
import Bundle from './Bundle'
const Dashboard = (props) => (
<Bundle load={() => import('./Dashboard')}>
{(Dashboard) => <Dashboard {...props}/>}
</Bundle>
);
複製代碼
路由部分沒有變化異步
<HashRouter>
<Switch>
<Route path='/' exact component={Index} />
<Route path='/dashboard' component={Dashboard} />
</Switch>
</Router>
複製代碼
這時候,執行npm start,能夠看到在載入最初的頁面時加載的資源以下 函數
而當點擊觸發到/dashboard路徑時,能夠看到 性能
代碼拆分在單頁應用中很是常見,對於提升單頁應用的性能與體驗具備必定的幫助。按需加載的方式還不止這一種,還可使用require.ensure()或者一些loader也能夠一樣實現這個功能。
若是加載的js很大,或者用戶的網絡情況很差的話,須要加上一個loading的效果,這裏我用的是antd的Spin組件。在render函數的mod沒set的時候加上就能夠了。
render() {
let spin = <div style={{textAlign: 'center', marginTop:50}}><Spin size="large"/><br/>正在玩命加載中。。。</div>;
return this.state.mod ? this.props.children(this.state.mod) : spin;
}
複製代碼