react系列(23)懶加載的應用

在使用Create React App創建的React項目,通常會通過import引用所需的組件(如import HelloWorld from './HelloWorld'),當項目打包成生產環境代碼時,通過這種方式引用的js文件都會被打包到一起。當前端項目代碼量足夠大時,這意味最終打包出來的index.js代碼量也將會非常大,這明顯不利於實現頁面的秒加載。遇到這種場景,懶加載就提供瞭解決方案。懶加載的根本就是代碼分割,它可以將不需要在首屏顯示的組件代碼獨立分割成一個文件,在適當的時候(如經過用戶交互後),再把這類組件動態加載出來。

React實現懶加載有兩種方式:

1. import().then();

import("./math").then(math => {
  console.log(math.add(16, 26));
});

以代碼爲例,用方式實現懶加載,在打包時會將import的內容即math.js獨立打包成一個文件,實現與主程序的代碼分割。

在實際應用中,常常會封裝成一個動態加載的高階組件asyncComponent:

import React, { Component } from 'react';
 
const asyncComponent = (importComponent) => {
  return class extends Component {
    constructor() {
      super();
      this.state = {
        component: null
      };
    }
    componentDidMount() {
      importComponent()
        .then(cmp => {
          this.setState({ component: cmp.default });
        });
    }
    render() {
      const C = this.state.component;
      return C ? <C {...this.props} /> : null;
    }
  };
};
 
export default asyncComponent;

asyncComponent應用於路由的懶加載實現:

<Switch>
    <Route exact path="/" component={AsyncComponent(() => import('./routes/Home'))}></Route>
    <Route path="/about" component={AsyncComponent(() => import('./routes/About'))}></Route>
</Switch>

2.React.lazy

React.lazy 接受一個函數,這個函數需要動態調用 import()。它必須返回一個 Promise,該 Promise 需要 resolve 一個 defalut export 的 React 組件。React.lazy通常與React.Suspense配合使用。

import React, { lazy, Suspense } from 'react';

const CompA = lazy(() => import('./CompA'));
class Test extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        const visible = false;
        return (
            <div>
                {visible ?
                    <Suspense fallback={<div>Loading...</div>}>
                        <CompA />
                    </Suspense> : null}
            </div>
        );
    }
}

export default Test;

在上述代碼中,組件CompA不會被馬上加載進來,只有當visible爲true時,纔會被動態加載進來。

當項目打包時,與第一種方式相同,CompA.js會被獨立打包出來,打包出來的文件會通過動態加載的方式引用到項目中。

React.lazy應用於路由懶加載實現:

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章