javascript - React 中的惰性是什么?

标签 javascript reactjs react-native

我正在阅读 React 官方文档以了解 React lazy。

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

This will automatically load the bundle containing the OtherComponent when this component gets rendered.

React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.

Normal import

import OtherComponent from './OtherComponent';
function MyComponent() {
    return (
        <div>
           <OtherComponent />
        </div>
    );
}

Lazy import

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

但我无法从文档中了解到使用惰性导入组件的优势。另外,为什么 promise 会出现在导入模块/组件的画面中?

最佳答案

单页应用程序 (SPA) 通常通过下载包含您的应用程序所需的所有脚本的 来工作。浏览器地址栏中的路由和 URL 更改通过 HTML5 history API 处理.这创造了令人难以置信的强大用户体验,因为浏览器永远不需要刷新来加载应用程序的任何部分 - 您可以立即从一个页面/URL 导航到另一个页面/URL。

虽然这在理论上听起来不错,但在实践中,情况却很糟糕。最大的问题之一是 bundle 的大小——在中等复杂度的 SPA 中, bundle 的大小很容易达到兆字节。现在,如此大的文件不仅需要很长时间才能下载,而且还没有被浏览器缓存 - 因此需要一次又一次地获取它们,这反过来又会使您的应用程序看起来很慢。

已经有很多尝试来解决这个问题 - asynchronous and deferred loading of scripts , 和代码拆分。代码拆分是指将大型包拆分为较小的 block 的技术 - 这个想法是您尽快下载应用程序的核心或关键部分,然后按需加载其余代码。这解决了上述问题,但事实证明实现代码拆分非常困难。

其中一个原因是,像 Webpack 这样的工具很难弄清楚如何有效地拆分代码,同时减少人工干预。在 AMD世界,define/require帮助您定义代码拆分点 - 因此您可以先加载关键部分,然后以异步方式按需加载其余部分。

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

() => import('./OtherComponent') 语法也称为dynamic import这与静态导入不同: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>
    );
  }
}

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

Suspense是 React 16.6 中的新 API。

与另一个即将推出的名为并发渲染的功能一起,上述代码确保 React 可以非常快速地渲染应用程序(比 React 16 更快)。它可以这样做,因为 React 知道哪些部分是关键的,哪些部分不是。

为了进一步阅读,我建议这个 blog post它通过代码示例讨论了所有 3 个功能。

关于javascript - React 中的惰性是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53174915/

相关文章:

javascript - Rails Controller 返回整个 React 应用程序

ios - React 本地 map 集成

javascript - 无法将 mst 模型数据从一个模型复制到另一个模型

javascript - 浏览历史记录时非 SPA 应用程序中的 Backbone.js 出现问题

javascript - AngularJS 无法获取 JSON 数据

javascript - 最大高度无法正常工作

javascript - React JSX 中最后一次循环迭代的条件?

javascript - 设置HTML Canvas 弧线的属性

javascript - 对象的 React setState 不正确

javascript - React-Native - undefined 不是对象 (“evaluating _react3.default.PropTypes.shape” )