React中有什么懒惰?

Hem*_*ari 3 javascript reactjs react-native

我正在阅读react官方文档以了解关于react lazy的知识。

根据文档, https://reactjs.org/docs/code-splitting.html#reactlazy

呈现此组件时,这将自动加载包含OtherComponent的捆绑包。

React.lazy采用必须调用动态函数的函数import()。这必须返回Promise解析为模块的模块,该模块具有包含React组件的默认导出。

正常导入

import OtherComponent from './OtherComponent';
function MyComponent() {
    return (
        <div>
           <OtherComponent />
        </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

懒导入

const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
    return (
       <div>
           <OtherComponent />
      </div>
    );
}
Run Code Online (Sandbox Code Playgroud)

但是我从文档中对使用惰性导入组件的优势了解得不多。另外,为什么承诺会在导入模块/组件时成为现实?

dan*_*die 7

简而言之,如果您延迟加载的组件未被使用,则浏览器中不会下载该组件。

在下面的代码中,Hello&Bye被导入。但由于Hello使用了 only,因此Bye不包括 for 的代码。

import React, { lazy, Suspense } from "react";
import ReactDOM from "react-dom";

const Hello = lazy(() => import("./components/Hello"));
const Bye = lazy(() => import("./components/Hello"));

function App() {
  return (
    <Suspense fallback={<>Loading...</>}>
      <Hello />
    </Suspense>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Run Code Online (Sandbox Code Playgroud)

您可以在CodeSandbox上关注
编辑so.answer.53174915

当您在 Netlify 上检查已部署的站点时,您可以看到未加载的
站点。Bye

在此输入图像描述


您可以通过按需加载组件来利用这一点。

无耻插件:如果您想了解更多有关其他用例的信息,请查看我的博客文章,使用 React.lazy 按需动态加载 React 组件


Mrc*_*ief 7

单页应用程序(SPA)通常通过下载包含应用程序所需的所有脚本的捆绑包来工作。浏览器地址栏中的路由和URL更改是通过HTML5历史API处理的。由于浏览器无需刷新就可以加载应用程序的任何部分,因此可创建强大的用户体验,您可以立即从一个页面/ URL导航到另一个页面/ URL。

从理论上讲,这听起来不错,但实际上,情况却很丑陋。最大的问题之一是捆绑包的大小-在中等复杂度的SPA中,捆绑包的大小很容易达到兆字节。现在,如此大的文件不仅需要花费很长时间下载,而且也不会被浏览器缓存-因此需要一次又一次地获取它们,这反过来会使您的应用程序显得呆滞。

已经进行了许多尝试来纠正此问题- 异步和延迟加载脚本以及代码拆分。代码拆分是指将大型捆绑包拆分成较小的块的技术 -其想法是您尽快下载应用程序的核心或关键部分,然后按需加载其余代码。这解决了上面提到的问题,但是实现代码拆分非常困难。

原因之一是,Webpack之类的工具很难通过较少的人工干预来弄清楚如何有效地拆分代码。在AMD世界中,define/require帮助您定义了代码分割点-因此,您可以先加载关键部件,然后按需求以异步方式加载其余部件。

在React世界中,lazy您可以通过更少的人工干预来有效地做到这一点。通过定义某些内容lazy,可以表明这部分代码是非关键的,可以根据需要在后台加载。

() => import('./OtherComponent')语法也被称为动态导入这从静态导入不同:import OtherComponent from './OtherComponent'。动态导入是异步的,因此它们始终返回Promise。一个Promise确保仅在脚本加载后执行依赖于此延迟加载的模块的代码。

考虑以下代码段:

const PurchaseHistory = lazy(() => import('./components/PurchaseHistory'))

class App extends Component {
  state = {
    purchases: [ ],
  };

  componentDidMount() {
    fetch(`some/api/that/returns/data`)
      .then(res => res.json())
      .then(res => {
        this.setState({ purchases: res.data });
      });
  }
  render() {    
    return (
      <div className="app">
        <Suspense fallback={Loader}>
          <PurchaseHistory {...purchases} />
        </Suspense>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,React可以立即使用Loader和渲染应用程序,直到获取成功为止,它甚至不需要加载惰性PurchaseHistory组件。这样可以节省下载时间,减少内存占用,并节省下载和处理PurchaseHistory组件所需的CPU周期。

Suspense是React 16.6中的新API。

上面的代码与即将推出的另一个功能Concurrent Rendering结合在一起,可以确保React快速地渲染应用程序(比React 16更快)。之所以可以这样做,是因为React知道哪些部分至关重要,哪些不重要。

为了进一步阅读,我建议这篇博客文章讨论所有3个功能以及代码示例。


T.J*_*der 5

它允许您延迟加载其他组件的脚本。如果该脚本与其他脚本分开(例如,不是主包的一部分),这主要是有用的。

优点是:

  • 您的初始启动速度更快(假设您的组件不是初始显示的一部分)
  • 如果用户从不执行任何显示您的组件的操作,则永远不需要加载其他组件的脚本(这样就节省了 HTTP 请求和模块消耗的内存加载)

当然,也有缺点:

  • 当您的组件需要显示时,它将通过请求加载其他组件的脚本(HTTP 请求、顶级模块评估)来延迟
  • 如果您进行捆绑,则很复杂,现在您必须在捆绑包中包含一些脚本,而在捆绑包中则必须包含其他脚本

与往常一样,某些项目的权衡是一种方式,而另一些项目的权衡则是另一种方式。一个大型的单页应用程序,其中有很多用户可能会或可能不会访问的部分,可能会受益;一个小页面,其中所有组件可能都会提前呈现,但可能不会。