Webpack + react-router 按需加载

#1

webpack + react-router 按需加载

关键函数

require.ensure(dependencies, callback, chunkName)
详情请见官方文档

webpack 配置

output: {
    path: path.join(__dirname, '../dist'),
    filename: '[name].js',
    sourceMapFilename: '[file].map',
    publicPath: '/static/',
    //加这个!
    chunkFilename: '[name].[chunkhash:5].chunk.js',
},

name 表示创建的chunk的指定名字,如果未指定则用id作为name
chunkhash 是文件的 hash 码,用来保证文件的唯一性,这里使用前五位(前几位可随意选取)
####结合react-router
官方文档
中文文档在这里!
其中提供了三个函数分别是:

  • getChildRoutes
  • getIndexRoute
  • getComponents

他们的作用都是访问到当前路由时才会去加载脚本,由此按需加载便得以实现。 官方的例子中使用的是以对象的形式构建路由,在此,我觉得用jsx更加直观。 所以我们需要将原本Route组件的component属性换成getComponent以此来运行我们的关键函数

####示例代码 ```javascript import React from 'react'; import { Route, IndexRedirect, } from 'react-router'; import rootNode from './rootNode';

const routes = (




<Route
path=‘index’
getComponent={(location, cb) => {
require.ensure([], require => {
cb(null, require(‘components/Index’).default);
}, ‘index’);
}} />


);

export default routes;

这样按需就在就完成了,但是我们可以用更优雅的方式来写。
```javascript
import React from 'react';
import {
    Route,
    IndexRedirect,
} from 'react-router';
import rootNode from './rootNode';

const index  = (location, cb) => {
  require.ensure([], require => {
    cb(null, require('components/Index').default);
  }, 'index');
};

const routes = (
        <Route path='/' component={rootNode}>
            <IndexRedirect to='index' />
            <Route path='index' getComponent={index} />
        </Route>
    );

export default routes;

将对应组件的加载函数进行封装,这样更加直观易懂。

####注意点

1、require('components/Index').defaultrequire方法的参数不能使用变量,只能使用字符串!
2、如果你的组件是使用es5的module.exports导出的话,那么只需要require('components/Index')即可。而如果你的组件是使用es6的export default导出的话,那么需要加上default!例如:require('components/Index').default
3、如果在路由页面使用了按需加载(require.ensure)加载路由级组件的方式,那么在其他地方(包括本页面)就不要再import了,否则不会打包生成chunk文件。简而言之,需要按需加载的路由级组件必须在路由页面进行加载。

####我的项目地址
未使用redux:react-hot
使用redux:react-redux-github

####参考
1、react-router 按需加载
2、webpack 按需打包加载
3、react-router官方示例

1 Like
#2

这里也有个按需加载的示例,一位高手写的。
https://github.com/bailicangdu/react-pxq/blob/master/src/Router/Route.jsx

#3

@hyy1115 嗯,他的代码我看过,从中学习到了很多。

#5

赞赞赞

#6

原文中的例子已经改了,我拷贝一下 :slight_smile:

import React, { Component } from 'react';

export default function asyncComponent(importComponent) {
    class AsyncComponent extends Component {
        constructor(props) {
            super(props);
            this.state = {
                component: null
            };
        }
        async componentDidMount() {
            const { default: component } = await importComponent();
            this.setState({ component });
        }
        render() {
            const C = this.state.component;
            return C ? <C {...this.props } /> : null;
        }
    }
    return AsyncComponent;
}
import asyncComponent from '../utils/asyncComponent'
const OrderList = asyncComponent(() => import('../view/order/list'))
const OrderDetail = asyncComponent(() => import('../view/order/detail'))

const routes = [
    {
        path: '/trade/order',
        component: OrderList,
        breadcrumbName: 'order',
        breadcrumbPath: '/trade/order'
    },
    {
        path: '/trade/order/detail',
        component: OrderDetail,
        breadcrumbName: 'order/detail',
        breadcrumbPath: '/trade/order/detail'
    }
]

export default routes