React 性能優化之組件動態加載(react-loadable)


React 項目打包時,如果不進行異步組件的處理,那么所有頁面所需要的 js 都在同一文件中(bundle.js),整個js文件很大,從而導致首屏加載時間過長。


所有,可以對組件進行異步加載處理,通常可以使用 React-loadable

React-loadable 使用

例如,對於項目中的detail組件(/src/pages/detail/),在 detail 目錄下新建 loadable.js:

import React from 'react';
import Loadable from 'react-loadable';

const LoadableComponent = Loadable({
  loader: () => import('./index.js'),
  loading() {
      return <div>正在加載</div>
  },
});

export default () => <LoadableComponent/>

然后在 app.js 里面引入detail組件:

// 不適用 react-loadable 時的引入方式:
// import Detail from './pages/detail/index';


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

... ...

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <Fragment> 
          <BrowserRouter>
            ··· ···
                <Route path='/detail/:id' exact component={Detail}></Route>
            ··· ···
          </BrowserRouter>
        </Fragment>
      </Provider>
    )
  }
}

但是,在/pages/detail/index.js文件中,如果想訪問到當前路由的 match,location,history對象,就訪問不到了

需要使用 withRouter 對 /detail/index.js 作如下處理:

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));

withRouter 可以將一個非路由組件包裹為路由組件,使這個非路由組件也能訪問到當前路由的match, location, history對象。

統一處理

上面已經實現了動態加載 detail 組件的方式,但是如果有多個組件時,需要在每個組件下新建 loadable.js ,比較麻煩,所有可以統一封裝處理所有組件的動態加載。

新建目錄/src/utils,新建文件 /src/utils/loadable.js

import React from 'react';
import Loadable from 'react-loadable';

export default (loader) => {
    return Loadable({
        loader,
        loading() {
            return <div>正在加載</div>
        },
    });
}

在 app.js 中,

import loadable from './utils/loadable';
import Header from './common/header'; 

<!--異步加載組件-->
const Home = loadable(() => import('./pages/home'));
const Detail = loadable(() => import('./pages/detail'));
const Login = loadable(() => import('./pages/login'));
const Write = loadable(() => import('./pages/write'));
  
class App extends Component {

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

export default App;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM