观察一下我们的webpack.config.*.js里面的output配置有个chunkFilename,这个就是我们通过webpack编译输出后用来命名分割后的代码文件名称的。
这里有个关于webpack不同版本针对代码分割做却别设置的问题:代码里的[name]默认是id覆盖,如果你要给chunkFilename重新起名字,要使用webpack1的require.ensure()或webpack2以上的import()方法。

webpack1.v

1
require.ensure(dependencies: String[], callback: function(require), chunkName: String)

上面的chunkName对应的就是webpack里的chunkFilename里的[name]

webpack2.v-3.v

1
2
3
const Foo = asyncComponent(() => import(/* webpackChunkName: "foo" */ "./foo"))

<Route path="/xx" component={Foo} />

上面的import()是webpack2以上版本的写法,注意\/ webpackChunkName: “foo” \/,这里对应的就是webpack里的chunkFilename里的[name]。

上面的原文链接可点击这里查看

重点开始!!!我们看到webpack2-3以后用来分割代码所使用的是 import() ,然后我们定义一个 asyncComponent() 的方法将import() 进来的内容通过 Promise (import 其实就是Promise的使用)再转化成 AsyncComponent 组件赋值给对应的 Foo 组件。所有,我这重点讲的就是实现 asyncComponent() 的方法。

我们在项目目录下面建一个utils目录,然后再建一个asyncComponent.js文件,再把如下代码贴进去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import \* as React from 'react';  
import PropTypes from 'prop-types';

export default function asyncComponent(importComponent) {
class AsyncComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentWillMount() {
const { default: component } = await importComponent();
this.setState({ component: component });
}
componentDidMount() {
if (this.props.title) {
document.title = this.props.title;
}
}
render() {
const Component = this.state.component;
return Component ? <Component {...this.props} /> : null;
}
}
AsyncComponent.propTypes = {
title: PropTypes.string,
};
return AsyncComponent;
}

保存即可,然后在routes.js文件里面引入asyncComponent方法。

这里我们的代码片段都是基于之前的React项目实战教程来的,如果不清楚的地方,可以回看之前的教程。

友情提示:
如果我们之前开启了eslint检测,那么当前的按需加载的实现会在eslint时报错误提示Unexpected token componentWillMount,这是因为我们用了es7的东西以及import()的方法导致的。
此时,我们只需要在eslint的配置文件上加上"parser": "babel-eslint",就可以了。ps:这个问题搞了我大半天,一直以为是webpack编译不能理解es7或不能直接使用import()导致的,fuck!!!