和异步加载script的目的一样(异步加载script的方法),按需加载/代码切割也可以解决首屏加载的速度。
什么时候需要按需加载
如果是大文件,使用按需加载就十分合适。比如一个近1M的全国城市省市县的json文件,在我首屏加载的时候并不需要引入,而是当用户点击选项的时候才加载。如果不点击,则不会加载。就可以缩短首屏http请求的数量以及时间。
如果是小文件,可以不必太在意按需加载。过多的http请求会导致性能问题。
二、实现按需加载的方法Webpack打包模块工具实现
RequireJs实现
这里介绍React-router+Webpack实现按需加载的功能,效果如下:
注意!我这里使用的是最新版本的React-router-dom^4.3.1.如果是4.0以下的react-route可直接看四
4.0相比以前实现方式要复杂。需要引入bundle-loader模块。并且自己创建bundle模型实现。
1.创建包装组件模型bundle.jsimport 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
});
props.load(mod => { this.setState({
mod: mod.default ? mod.default : mod
});
});
}
render() {
return this.state.mod ? this.props.children(this.state.mod) : null;
}
}
export default Bundle ;2.创建包装组件的方法(函数)// 懒加载方法import React from 'react'; import Bundle from './Bundle'; console.log(Bundle);// 默认加载组件,可以直接返回 nullconst Loading = () => Loading...;const lazyLoad = loadComponent => props => ({Comp => (Comp ? ); console.log(lazyLoad); export default lazyLoad; //实际上lazyLoad就是一个函数,组件调用即可: )}
上面两个文件的关系:
lazyLoad.js从名字上看,叫懒加载.实际上是一个中间件的作用。最后lazyLoad会暴露一个函数出来供组件调用。lazyLoad导出的内容:
function lazyLoad(loadComponent) { return function(props) { return (
{Comp => (Comp ? : )}
)
}
}显而易见,loadComponent就是要加载的组件,在路由中调用,例如:异步调用page1组件
Bundle.js作为按需加载的核心,在lazyLoad中间件就已经引入,并传入一个自定义的方法load,值为组件内容。以及动态的子内容children:
{Comp => (Comp ? : )}最终返回组件信息,并附带相应的props.如果不存在相关组件,则Loading
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(
PAGE1
PAGE2
PAGE3
(
)}
/>
)
}
}
export default AppPage;几个注意的点:
其中bundle-loader表示loader:'bunle-loader'(需加载bundle-loader模块)
lazy表示lazy:true;懒加载
name:表示异步生成的文件名字
去掉外层route,不用render渲染也是可行的
import异步加载组件的时候,名字变更为'bundle-loader?lazy&name=page1!../components/page1/index'
//webpack.config.js... module.exports = {
...
output:{
path:path.join(__dirname + '/dist'), //打包地方
filename:'bundle.js', //打包名字
publicPath: '/', //自动生成html引入js的路径
//按需加载
chunkFilename:'[name]_[chunkhash:8].js'
},
...
}
...这里要注意一下publicPath这个参数.
如果未设置publicPath参数,则默认打包生成的html引入bundle的时候为:
如果设置publicPath为publicPath: '/dist',则打包后html文件引入js格式为:
参考文章:React-router-v4 - Webpack 实现按需加载(code-splitting)
原文出处:https://www.cnblogs.com/soyxiaobi/p/9535292.html



