思净 發表於 2019-9-9 16:31:00

React 性能优化之组件动态加载(react-loadable)

<p>React 项目打包时,如果不进行异步组件的处理,那么所有页面所需要的 js 都在同一文件中(bundle.js),整个js文件很大,从而导致首屏加载时间过长。</p>
<hr>
<p>所有,可以对组件进行异步加载处理,通常可以使用 <code>React-loadable</code>。</p>
<h2 id="react-loadable-使用">React-loadable 使用</h2>
<p>例如,对于项目中的detail组件(/src/pages/detail/),在 detail 目录下新建 loadable.js:</p>
<pre><code>import React from 'react';
import Loadable from 'react-loadable';

const LoadableComponent = Loadable({
loader: () =&gt; import('./index.js'),
loading() {
      return &lt;div&gt;正在加载&lt;/div&gt;
},
});

export default () =&gt; &lt;LoadableComponent/&gt;
</code></pre>
<p>然后在 app.js 里面引入detail组件:</p>
<pre><code>// 不适用 react-loadable 时的引入方式:
// import Detail from './pages/detail/index';


// 使用 react-loadable 时的引入方式:
import Detail from './pages/detail/loadable';

... ...

class App extends Component {
render() {
    return (
      &lt;Provider store={store}&gt;
      &lt;Fragment&gt;
          &lt;BrowserRouter&gt;
            ··· ···
                &lt;Route path='/detail/:id' exact component={Detail}&gt;&lt;/Route&gt;
            ··· ···
          &lt;/BrowserRouter&gt;
      &lt;/Fragment&gt;
      &lt;/Provider&gt;
    )
}
}
</code></pre>
<h4 id="但是在pagesdetailindexjs文件中如果想访问到当前路由的-matchlocationhistory对象就访问不到了">但是,在/pages/detail/index.js文件中,如果想访问到当前路由的 match,location,history对象,就访问不到了</h4>
<p>需要使用 <code>withRouter</code> 对 /detail/index.js 作如下处理:</p>
<pre><code>import { withRouter } from 'react-router-dom';

class Detail extends Component {
    render() {
      ··· ···
    }

    componentDidMount() {
      // withRouter处理后,就可以在这里拿到 match 对象了
      console.log(this.props.match);
      this.props.getDetail(this.props.match.params.id);
    }
}

··· ···

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Detail));
</code></pre>
<p>withRouter 可以将一个非路由组件包裹为路由组件,使这个非路由组件也能访问到当前路由的match, location, history对象。</p>
<h2 id="统一处理">统一处理</h2>
<p>上面已经实现了动态加载 detail 组件的方式,但是如果有多个组件时,需要在每个组件下新建 loadable.js ,比较麻烦,所有可以统一封装处理所有组件的动态加载。</p>
<p>新建目录/src/utils,新建文件 /src/utils/loadable.js</p>
<pre><code>import React from 'react';
import Loadable from 'react-loadable';

export default (loader) =&gt; {
    return Loadable({
      loader,
      loading() {
            return &lt;div&gt;正在加载&lt;/div&gt;
      },
    });
}
</code></pre>
<p>在 app.js 中,</p>
<pre><code>import loadable from './utils/loadable';
import Header from './common/header';

&lt;!--异步加载组件--&gt;
const Home = loadable(() =&gt; import('./pages/home'));
const Detail = loadable(() =&gt; import('./pages/detail'));
const Login = loadable(() =&gt; import('./pages/login'));
const Write = loadable(() =&gt; import('./pages/write'));

class App extends Component {

render() {
    return (
      &lt;Provider store={store}&gt;
      &lt;Fragment&gt;
          &lt;BrowserRouter&gt;
            &lt;div&gt;
            &lt;Header /&gt;
            &lt;Switch&gt;
                &lt;Route
                  exact
                  path="/"
                  render={() =&gt; &lt;Redirect to="/home" /&gt;}
                /&gt;
                &lt;Route path='/home' exact component={Home}&gt;&lt;/Route&gt;
                &lt;Route path='/login' exact component={Login}&gt;&lt;/Route&gt;
                &lt;Route path='/write' exact component={Write}&gt;&lt;/Route&gt;
                &lt;Route path='/detail/:id' exact component={Detail}&gt;&lt;/Route&gt;
                &lt;Route render={() =&gt; &lt;div&gt;Not Found&lt;/div&gt;} /&gt;
            &lt;/Switch&gt;
            &lt;/div&gt;
          &lt;/BrowserRouter&gt;
      &lt;/Fragment&gt;
      &lt;/Provider&gt;
    )
}
}

export default App;
</code></pre><br><br>
来源:https://www.cnblogs.com/cckui/p/11492510.html
頁: [1]
查看完整版本: React 性能优化之组件动态加载(react-loadable)