- 安装Bundle Loader
npm i bundle-loader --save
- 创建bundle.js
import React from 'react';
class Bundle extends React.Component {
constructor(arg){
super(arg)
this.state = {
mod: null,
}
}
componentWillMount() {
this.load(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}
// load 方法,用于更新mod状态
load(props) {
// 初始化
this.setState({
mod: null
});
/*
调用传入的load方法,并传入一个回调函数
这个回调函数接收在load方法内部异步获取到组件,并将其更新为mod
*/
props.load(mod => {
this.setState({
mod: mod.default ? mod.default : mod
});
});
}
render() {
/*
将存在状态中的mod组件作为参数传递给当前包装组件的子组件
*/
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
export default Bundle ;
- 创建lazyLoad.js文件
// 懶加載方法
import React from 'react';
import Bundle from './Bundle';
console.log(Bundle);
// 默认加载组件,可以直接返回null
const Loading = () => <div>Loading...</div>;
/*
包装方法,第一次调用后悔返回一个组件(函数式组件)包装方法,第一次调用后会返回
由于要将其作为路由下的组件,所以需要将props传入
*/
const lazyLoad = loadComponent => props => (
<Bundle load={loadComponent}>
{Comp => (Comp ? <Comp {...props} /> : <Loading />)}
</Bundle>
);
console.log(lazyLoad);
export default lazyLoad; // 实际上lazyLoad就是一个函数,组件调用即可
- 使用
import React from 'react';
import { NavLink,Route,Switch,BrowserRouter as Router } from 'react-router-dom'
import './style/style.css'
import 'bundle-loader'
// bundle模型用來異步加載組件
import Bundle from '../routes/Bundle.js';
import lazyLoad from '../routes/lazyLoad';
import Page1 from 'bundle-loader?lazy&name=page1!../components/page1/index';
import Page2 from 'bundle-loader?lazy&name=page2!../components/page2/index';
import Page3 from 'bundle-loader?lazy&name=page3!../components/page3/index';
class AppPage extends React.Component{
constructor(arg){
super(arg)
this.state={}
}
render(){
return(
<Router basename="/" >
<div className="appWried">
<div className="appBtn">
<NavLink to="/page1" className="button" activeClassName="active">
PAGE1
</NavLink>
<NavLink to="/page2" className="button" activeClassName="active">
PAGE2
</NavLink>
<NavLink to="/page3" className="button" activeClassName="active">
PAGE3
</NavLink>
</div>
<Switch>
<Route path="/page1" component={lazyLoad(Page1)}/>
<Route path="/page2" component={lazyLoad(Page2)}/>
<Route path="/page3" component={lazyLoad(Page3)}/>
</Switch>
</div>
</Router>
)
}
}
export default AppPage;
注意:
import 异步加载组件的时候,名字部分变更为
'bundle-loader?lazy&name=page1!../components/page1/index'
其中,bundle-loader表示按需加载模块,lazy表示lazy:true;懒加载
name表示异步生成的文档名字
//webpack.config.js
...
module.exports = {
...
output:{
path: path.join(__dirname, "../build"),//出口文件
filename: "[name].[hash:8].js",
publicPath: "/", //自動生成html引入js的路徑
//按需加載
chunkFilename:'[name].chunk.[hash:8].js'
},
...
}
这里需要注意一下publicPath这个参数。
如果未设置publicPath参数,折磨人打包生成html引入js文件为
<script type="text/javascript" src="bundle.js"></script>
如果设置publicPath为publicPath: './dist',则打包后html引入js的格式为:
<script type="text/javascript" src="/dist/bundle.js"></script>










网友评论