使用ReactSuspense进行代码拆分

来自菜鸟教程
跳转至:导航、​搜索

React.Suspense 以及 v16.6 中引入的 React.lazy() 添加了新功能,允许组件在实际渲染之前等待某些内容。 这项新功能使 React 组件的代码拆分和延迟加载变得轻而易举!

入门

要开始使用,您需要确保您使用的是 React v16.6 或更高版本。 如果您正在开始一个新项目,或者如果您正在使用不在正确版本上的旧项目,只需:

# Via npm
$ npm install --save react react-dom

# Or via Yarn
$ yarn add react react-dom

然后在您想要处理其他组件的延迟加载的组件中,导入 Suspenselazy

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

关于代码拆分

值得指出的是,虽然 Suspenselazy 允许您快速轻松地延迟加载组件,但如果您将整个应用程序捆绑到一个单独的应用程序中,您可能看不到太多好处像 Webpack 这样的脚本。

虽然超出了本文的范围,但您可以在 Webpack 文档 中阅读有关使用 Webpack 进行代码拆分的内容。

React.lazy()

lazy() 方法将一个函数作为第一个参数,该参数预计将 import 另一个组件,如下所示:

const SomeComponent = lazy(() => import('./SomeComponent');

因为 import 在传递给 lazy() 的函数内部,所以在我们实际使用组件之前不会加载组件,而不是在顶部急切地加载其他导入你的文件。

React.Suspense

React.Suspense 组件允许我们包装一个组件并指定一个 fallback 组件,该组件将在包装的组件加载时显示:

<Suspense fallback={<div>Loading...</div>}>
  <SomeComponent />
</Suspense>

当您加载较大的组件或发生在 import 大型库(如 react-pdfreact-draft-wysiwyg)的组件时,这尤其有用。

即使您的组件不在重量级部门,延迟加载也可以帮助可能没有最佳 Internet 连接的最终用户。

把它们放在一起

要真正体验使用 React.SuspenseReact.lazy(),我们将需要两个单独的文件。 一个只是我们基本的 React 应用程序样板,另一个是我们将延迟加载的组件。

让我们从我们将要使用的组件开始 import。 在这个例子中,我创建了一个非常简单的组件来加载总是简洁的 Alligator.io 标志:

AlligatorioLogo.jsx

import React from "react";

function AlligatorioLogo() {
  const imageSource = "https://uploads.codesandbox.io/uploads/user"
    + "/39d6d9f6-60d2-4a60-9eb7-9250c3417bef"
    + "/saY6-alligatorio-logo.png";

  return (
    <img
      alt="Alligator.io Logo"
      src={imageSource}
      width="250"
    />
  );
}

export default AlligatorioLogo;

接下来是我们应用程序的样板代码和一小部分状态逻辑,以便我们可以手动触发组件的加载:

应用程序.jsx

import React, { Component, Fragment, lazy, Suspense } from "react";
import { render } from "react-dom";

import "./styles.css";

const AlligatorioLogo = lazy(() => import("./AlligatorioLogo"));

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showLogo: false
    };
  }

  onClick = () => {
    this.setState({ showLogo: !this.state.showLogo });
  };

  render() {
    return (
      <div className="App">
        <h1>React.lazy() + &lt;React.Suspense /&gt; Demo</h1>
        <div>
          <button onClick={this.onClick}>
            {this.state.showLogo &&
              <Fragment>Click to Hide the Logo</Fragment>
            }
            {!this.state.showLogo && (
              <Fragment>Click to Show the Logo</Fragment>
            )}
          </button>
        </div>
        <hr />
        {this.state.showLogo && (
          <Suspense fallback={<div>Loading...</div>}>
            <AlligatorioLogo />
          </Suspense>
        )}
      </div>
    );
  }
}

const container = document.createElement("div");
document.body.appendChild(container);
render(<App />, container);

如您所见,使用 Suspenselazy() 真的没什么用。 由于它非常简单,将现有系统移植到它不应该是太大的负担,特别是如果您已经将组件拆分为单独的文件。

结论

React.lazy()React.Suspense 的引入是在帮助减少构建现代 Web 应用程序所需编写的样板代码量方面向前迈出的重要一步。

Suspense 虽然已经相当强大,但也不是没有缺点。 未来 v16 版本的 React 路线图上最大的缺失部分是使用 Suspense 进行数据获取的能力。

一旦此数据获取功能可用,Suspense 将能够等待诸如 AJAX 调用之类的事情,并在加载时显示备用组件。

还值得注意的是,Suspense 还没有完全准备好与服务器端渲染一起使用。

如果您准备好试一试 React.SuspenseReact.lazy(),您可以前往 CodeSandbox 以查看本文中的代码的实际应用!