为什么要代码分割?
我们经常会通过 webpack 打包我们的应用,产生一个 bundle.js 文件。随着我们的项目越写越复杂,bundle.js 文件会随之增大,严重影响了首屏加载速度。
由于该文件是唯一的,所以不管用户查看哪个页面、使用哪个功能,都必须先下载所有的功能代码。 当 bundle.js 大到一定程度,就会明显影响用户体验。此时,我们就需要 code splitting ,将代码分片,实现按需异步加载,从而优化应用的性能。
import('./math').then(res=>{
console.log(res.default)
});
import('./print').then(res=>{
res.default('from print')
});
dist
├── 0.bundle.js
├── 0.bundle.js.map
├── 1.bundle.js
├── 1.bundle.js.map
├── bundle.js
├── bundle.js.map
└── index.html以路由为中心进行代码分片
- 通过高阶组件函数返回一个React.Component
- 路由匹配成功则立即调用import()并展示组件
function AsyncComponent(loadComponent,placeholder='loading……'){
return class AyncComponent extends React.Component{
state = {
Child:null
}
async componentDidMount(){
loadComponent().then(res=>{
this.setState({
Child:res.default
})
})
}
render(){
const { Child } = this.state;
return (
Child ? <Child {...this.props} /> : placeholder
);
}
}
}
const App = ()=>{
return (
<Router>
<Route path="/m1" component={AsyncComponent(()=>{
return import('./pages/m1');
})} />
<Route path="/m2" component={AsyncComponent(()=>{
return import('./pages/m2');
})} />
</Router>
)
}
ReactDOM.render(<App />, document.getElementById('root'));以组件为中心进行代码分片
路由本身并没有什么特别的,它也是组件。如果以组件为中心进行代码分版,会带来额外的好处:
- 同一个组件中,针对不着急显示的部分,可以延迟其加载。
- 分割点不再局限于路由,可以任意指定
- 与路由匹配成功则加载不同,可以自行指定加载时机
function DelayComponent(loadComponent,delay=2000,placeholder='loading……'){
return class AyncComponent extends React.Component{
state = {
Child:null
}
async componentDidMount(){
this.timer = setTimeout(() => {
loadComponent().then(res=>{
this.setState({
Child:res.default
})
})
}, delay);
}
componentWillUnmount(){
this.timer && clearTimeout(this.timer);
}
render(){
const { Child } = this.state;
return (
Child ? <Child {...this.props} /> : placeholder
);
}
}
}
const DelayM1Child = DelayComponent(()=>import('./m1Child'),2000);
export default class M1 extends React.Component {
render() {
return (
<div>
<div>m111111</div>
<DelayM1Child />
</div>
)
}
}demo 地址: