React 组件的懒加载

1,775 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

从初始化的性能上来说,尽量减少代码的初次加载数量,Web应用一个重要的优势就在于可以只加载我们想要的功能,而不必每次打开都把整个系统载入。

文章主要介绍三种方法:

  • 借助三方库 react-loadable
  • React.lazy() 和 Suspense
  • 结合 React-Router

1. 借助三方库 react-loadable

Loadable 是一个高阶组件

高阶组件(简单来说,就是把组件作为输入的组件。高阶函数就是把函数作为输入的函数。在 React 里,函数和组件有时是一回事

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

function Loading() {
  return <div>Loading.....</div>
}

const LoadableComponent = Loadable({
   loader: () => import('./OtherComp3'),
  loading: Loading,
});

function App() {
  return (
    <LoadableComponent/>
  );
}

export default App;

2. React.lazy() 和 Suspense

React.lazy 功能允许将动态导入呈现为常规组件。

之前的做法:

import OtherComp from './OtherComp'

function App() {
  return (
    <div>
      <OtherComp/>
    </div>
  );
}

export default App;

之后:

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

const OtherComp2 = lazy(() => import('./OtherComp2'))

function App() {
  return (
    <Suspense fallback={<div>loading....</div>}>
      <OtherComp2/>
    </Suspense>
  );
}

export default App;

React.lazy 所接收的参数必须是一个 动态调用的 import()函数且返回一个 Promise 解析为默认导出为React组件的模块。

为了给用户更好的体验,我们可以借助Suspense组件的 fallback 属性定义加载前的一些交互,fallback属性接受任何React元素。可以将Suspense组件放在 lazy组件层级上面的任意位置,同时Suspense组件可以包含多个lazy组件。

import React, { Suspense, useState, lazy } from 'react';
import OtherComp from './OtherComp'

const OtherComp2 = lazy(() => import('./OtherComp2'))
const OtherComp3 = lazy(() => import('./OtherComp3'))

function Loading() {
  return <div>Loading.....</div>
}

function App() {
  const [isShow, setIsShow] = useState(false)

  const handleClick = () => {
    setIsShow(true)
  }

  let lazyComps = null
  if (isShow) {
    lazyComps = <Suspense fallback={Loading()}>
      <OtherComp2 name="lazy加载" />
      <OtherComp3 name="lazy加载" />
    </Suspense>
  }

  return (
    <>
      <Suspense fallback={<div>Loading.....</div>}>
        <div className="App">
          <div>
            <OtherComp name="正常加载" />
          </div>
          <button onClick={handleClick}>加载组件 Comp 2 和 Comp3</button>
          <div>
            {lazyComps}
          </div>
        </div>
      </Suspense>
    </>
  );
}

export default App;

3. 结合 React-Router

引入 reacct-router-dom 库

npm install react-router-dom
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import OtherComp from './OtherComp'
const OtherComp2 = lazy(() => import('./OtherComp2'))

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading.....</div>}>
        <Switch>
          <Route exact path="/pageA" component={OtherComp} />
          <Route exact path="/pageB" component={OtherComp2} />
        </Switch>
      </Suspense>
    </Router>
  );
}

export default App;