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
相关文章
相关标签/搜索