现在的H5项目大多是单页应用,项目可能有多个页面,而我们在打包时一般会打包在一个bundle中,这就可能导致bundle过大,而且用户也并不是使用所有的页面。最好的方式是在用户使用某个页面时,在把这个页面的bundle.js加载执行。
懒加载或者按需加载即可解决这个问题,这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
如何实现
要实现懒加载需要修改两个点:
- webpack.config.js中output的修改,支持输出多个bundle。
- 需要拆分的模块,引入的时候需要使用动态引入。
配置文件修改
module.exports = {
entry: {
'app': './src/app.js'
},
output: {
path: resolve('dist'),
filename: 'js/[name].js',
chunkFilename: 'js/[name].chunk.js',
}
}
动态导入
当我们访问某个页面的时候在去加载对应的js bundle,所以需要用到动态导入,webpack 提供了两个类似的技术。第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案 的 import() 语法 来实现动态导入。第二种,则是 webpack 的遗留功能,使用 webpack 特定的 require.ensure。
这里使用第一种方法。
在Route中动态导入页面
例子:
// webpackChunkName: "home" 定义生成的js bundle名字即为home
const Home = asyncComponent(() => import(/* webpackChunkName: "home" */ '../containers/Chain/Home'))
const AllChain = asyncComponent(() => import(/* webpackChunkName: "home" */ '../containers/Chain/AllChain'))
const ApproveList = asyncComponent(() => import(/* webpackChunkName: "approve" */ '../containers/Approve/List'));
const ApproveSearch = asyncComponent(() => import(/* webpackChunkName: "approve" */ '../containers/Approve/Search'));
export default function Routes () {
return (
<Switch>{/* home */}
<Route exact path="/chain" component={Home}/>
<Route exact path="/chain/all" component={AllChain}/>
{/* approve */}
<Route path="/approve/list/:id" component={ApproveList}/>
<Route path="/approve/search/:id" component={ApproveSearch}/>
</Switch>
)
}
这里我们写了高阶组件 asyncComponent 来处理动态导入的组件。动态导入的组件是异步的,导致不能把组件拿来直接使用,我们需要等组件加载完之后,在去render component。
asyncComponent 的实现:
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: component
});
}
render() {
const C = this.state.component;
return C
? <C {...this.props} />
: null;
}
}
return AsyncComponent;
}
写这些代码的时候React还没有推出懒加载的功能,这里或许可以使用React.lazy来改造。