Closed yuxino closed 3 years ago
在日常开发中我们都会碰见需要异步加载组件的情况,就比如说一个后台项目。拥有各种权限的分配,部分成员看得见一些表图页面,而一部分人看不见。我们知道表图库比如Echart之累的都满大的,如果我们直接加载进来全部打包到一个bundle的话,整个bundle的体积会比较大。并且除此之外很多页面组件用不上,也许用户一直都不会访问到,所以也没有理由加载,浪费带宽和资源。
bundle
这里说的异步加载都是在围绕着router来说,因为router一般都会做这个处理。react开发者的话会选择react-router作为处理控制路由的库。我们先来看看两种不同的场景。使用了异步加载和没有使用异步加载。以我的博客dura来举例子。
router
react
react-router
我们来看看没有异步载的情况。全部都打包在一个bundle里面的写法。
import React, { Component } from 'react' import './css/App.css' import { Route, Switch } from 'react-router' import HomePage from 'page/HomePage' import AboutPage from 'page/AboutPage' import ArchivesPage from 'page/ArchivesPage' import ClosedPage from 'page/ClosedPage' import LabelPage from 'page/LablePage' import LabelsPage from 'page/LablesPage' import TimeLinePage from 'page/TimelinePage' import NotFoundPage from 'page/NotFoundPage' class App extends Component { render () { return ( <Switch> <Route exact path="/" component={HomePage} /> <Route exact path="/about" component={AboutPage} /> <Route exact path="/archives" component={ArchivesPage} /> <Route exact path="/closed" component={ClosedPage} /> <Route exact path="/labels" component={LabelsPage} /> <Route exact path="/label/:number" component={LabelPage} /> <Route exact path="/timeline" component={TimeLinePage} /> <Route component={NotFoundPage} /> </Switch> ) } } export default App;
我们发现所有东西都打包在了一起,而不是针对页面进行打包,这样会加载无用资源。此时的bundle会是700kb,对我这个项目来说。
我们来看看异步加载的情况。
我们可以利用webpack 2.0+的特性import(...)语法来做异步加载,这样webpack会自动进行代码的chunk。只有在需要用到的时候才会引用。利用这一特性我们创建一个AsyncComponet的HOC组件帮助我们进行异步加载。
webpack 2.0+
import(...)
AsyncComponet
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; }
import React, { Component } from 'react' import './css/App.css' import { Route, Switch } from 'react-router' // using webpack import syntax up performance import AsyncComponent from 'hoc/AsyncComponent' const HomePage = AsyncComponent(() => import('page/HomePage')) const AboutPage = AsyncComponent(() => import('page/AboutPage')) const ArchivesPage = AsyncComponent(() => import('page/ArchivesPage')) const ClosedPage = AsyncComponent(() => import('page/ClosedPage')) const LabelPage = AsyncComponent(() => import('page/LablePage')) const LabelsPage = AsyncComponent(() => import('page/LablesPage')) const TimeLinePage = AsyncComponent(() => import('page/TimelinePage')) const NotFoundPage = AsyncComponent(() => import('page/NotFoundPage')) class App extends Component { render () { return ( <Switch> <Route exact path="/" component={HomePage} /> <Route exact path="/about" component={AboutPage} /> <Route exact path="/archives" component={ArchivesPage} /> <Route exact path="/closed" component={ClosedPage} /> <Route exact path="/labels" component={LabelsPage} /> <Route exact path="/label/:number" component={LabelPage} /> <Route exact path="/timeline" component={TimeLinePage} /> <Route component={NotFoundPage} /> </Switch> ) } } export default App;
我们现在再来看bundle的大小,我们会发现bundle缩小到了400kb左右,虽然这个小项目不是太明显也就是缩少了大概百分之40这样子。但是对于大型项目来说,这个倍率会网上递增。
除此之外在我们访问不同的页面的时候,才会对应的chunk。
chunk
AsyncCompoent利用了webpack的懒加载/code spliting特性达到了异步加载的目的。但是AsyncComponet并不完整,存在着很多的问题,比如说加载失败的问题,这里就没有处理,延迟加载,服务端处理,细节上的也没有,比如加载组件过程中的占位(placeholder)组件。
AsyncCompoent
webpack
懒加载/code spliting
一个更好的解决方案会是使用react-loadable组件做这个事情。不过这篇不做介绍,放下一次吧(可能)。
在日常开发中我们都会碰见需要异步加载组件的情况,就比如说一个后台项目。拥有各种权限的分配,部分成员看得见一些表图页面,而一部分人看不见。我们知道表图库比如Echart之累的都满大的,如果我们直接加载进来全部打包到一个
bundle
的话,整个bundle
的体积会比较大。并且除此之外很多页面组件用不上,也许用户一直都不会访问到,所以也没有理由加载,浪费带宽和资源。这里说的异步加载都是在围绕着
router
来说,因为router
一般都会做这个处理。react
开发者的话会选择react-router
作为处理控制路由的库。我们先来看看两种不同的场景。使用了异步加载和没有使用异步加载。以我的博客dura来举例子。没有异步加载组件的情况
我们来看看没有异步载的情况。全部都打包在一个
bundle
里面的写法。NetWorkd加载的情况
我们发现所有东西都打包在了一起,而不是针对页面进行打包,这样会加载无用资源。此时的bundle会是700kb,对我这个项目来说。
使用异步加载
我们来看看异步加载的情况。
我们可以利用
webpack 2.0+
的特性import(...)
语法来做异步加载,这样webpack会自动进行代码的chunk。只有在需要用到的时候才会引用。利用这一特性我们创建一个AsyncComponet
的HOC组件帮助我们进行异步加载。AsyncComponet.js
App.js
NetWorkd加载的情况
我们现在再来看
bundle
的大小,我们会发现bundle
缩小到了400kb左右,虽然这个小项目不是太明显也就是缩少了大概百分之40这样子。但是对于大型项目来说,这个倍率会网上递增。除此之外在我们访问不同的页面的时候,才会对应的
chunk
。总结
AsyncCompoent
利用了webpack
的懒加载/code spliting
特性达到了异步加载的目的。但是AsyncComponet
并不完整,存在着很多的问题,比如说加载失败的问题,这里就没有处理,延迟加载,服务端处理,细节上的也没有,比如加载组件过程中的占位(placeholder)组件。一个更好的解决方案会是使用react-loadable组件做这个事情。不过这篇不做介绍,放下一次吧(可能)。