react-router4的按需加載實踐(基於create-react-app和Bundle組件)

最近在網上也看到了react-router4的好多種按需加載的方法。react

傳送門:https://blog.csdn.net/foralienzhou/article/details/73437057npm

雖然本身的項目不大,可是也要區分前臺和後臺,若是讓訪問前臺的用戶也加載了後臺的js代碼,仍是很影響體驗的,因此挑了一種按需加載的方法進行實踐(基於create-react-app和Bundle組件)。bash

import()

這裏的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,能夠看到在載入最初的頁面時加載的資源以下 函數

image

而當點擊觸發到/dashboard路徑時,能夠看到 性能

image

代碼拆分在單頁應用中很是常見,對於提升單頁應用的性能與體驗具備必定的幫助。按需加載的方式還不止這一種,還可使用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;
}
複製代碼

image
相關文章
相關標籤/搜索