延迟加载与预先加载

**由 Njong Emy✏️ 撰写**

在软件开发领域,性能是一项至关重要的指标。应用程序如何才能在不牺牲性能的情况下处理和执行多个请求?需要注意的是,性能取决于数据的访问方式。如果应用程序需要访问大量数据,这可能会影响加载时间,从而影响性能。这并不能阻止某些应用程序在不牺牲客户端和服务器之间传递数据的速度的情况下处理大量数据。

在本文中,我们将探讨两种简单的数据访问技术:延迟加载和错误加载。对于每种方法,我们将了解用例和优势,以及如何在 React 等单页应用程序 (SPA) 框架中实现这些技术。

什么是延迟加载?

延迟加载是一种数据访问技术,即仅在需要时才加载资源。在这种情况下,资源包括视频、图片、脚本或组件。例如,如果您在网页上滚动,则该页面上的图片仅在您滚动到它时才会加载。

延迟加载是改善用户体验和性能的好方法,因为对服务器的查询保持在最低限度,并且应用程序只专注于运行当时需要的操作。

延迟加载的好处

  • 加载时间更快:由于资源的获取和加载被优先考虑,当页面首次加载时,初始加载时间要快得多
  • 改善用户体验:想象一下打开一个网页并等待长达一分钟才能完全加载页面。通过仅在需要时加载资源,可以轻松避免此问题。延迟加载可减少等待时间,从而提高客户满意度。
  • 减少带宽使用量:带宽是每秒在客户端和服务器之间传输的数据量。使用延迟加载,带宽使用量会显著减少,因为并非所有资源都会一次加载
  • 提高性能:当页面加载内容过多时,浏览器会花时间确保内容按应有的方式呈现。这有时会导致布局渲染不佳和性能下降。使用延迟加载方法,浏览器无需做太多工作即可确保页面正确加载
  • 延迟加载的缺点

  • 对于应用程序某一部分的数据依赖于另一部分的情况,延迟加载方法并不理想
  • 与其他技术相比,使用延迟加载时,需要进行更多数据库调用。这是因为数据不是一次性全部获取的,而是必须在应用程序的不同时间点连续获取
  • 什么是预先加载?

    使用预加载,应用程序运行所需的所有资源都会预先加载。页面首次加载后,所有图像、脚本和组件都会从服务器获取。

    对于需要将某个部分的数据提供给其他部分的应用,预加载尤其有用。这在仪表板应用中很常见。

    预先加载的好处

  • 更少的数据库查询:与延迟加载策略不同,急切加载涉及更少的数据库查询。由于所有资源都是一次性加载的,因此客户端无需反复查询后端来加载页面的其他部分
  • 简化代码:与延迟加载不同,急切加载无需明确寻找延迟加载资源的方法。因此,这种方法涉及更简单、更不复杂的代码
  • 数据一致性:即时加载可确保数据一致性,因为所有相关数据都会一次性获取。这在进程在查询之间在后台修改数据的场景中非常有用。
  • 预先加载的缺点

  • 带宽使用量增加,因为初始加载时客户端和服务器之间每秒发送的数据量很大
  • 采用预先加载方法,初始加载时间和等待时间会变慢
  • 如果实施不当,预加载可能会损害应用程序的性能。浏览器突然必须同时管理大量数据并确保布局正确显示
  • 使用预先加载时,通常会有不必要的数据获取。想象一下一个社交媒体应用程序,其中有一个用户表和一个帖子表,我们希望在一个查询中获取它们。在我们需要获取用户姓名及其最新帖子的情况下,预先加载会获取不必要的数据(该用户的所有帖子),从而导致过度获取和性能问题
  • 延迟加载和预先加载之间的区别

    React 中的延迟加载

    像 React 这样的单页应用程序 (SPA) 框架具有实现延迟加载和预先加载的默认方法。通过使用 React 中的 `[Suspense](https://blog.logrocket.com/data-fetching-react-suspense/)` 和 `React.lazy` 函数,我们可以看到如何通过单击按钮随意加载组件。

    假设我们有一个组件,稍后只需在应用程序中使用。我们将把它实现为单击按钮即可加载的组件。我们将该组件称为“MyLazyComponent”:

    const MyLazyComponent = () => {
      return (
        

    Look, I am the lazy component that is loaded after a button click

    ) } export default MyLazyComponent

    现在我们有了要延迟加载的组件,让我们看看 React 如何通过其内置的 React.lazy 函数实现延迟加载:

    import React, { Suspense, useState } from "react"
    
    const LazyComponent = React.lazy(() => import('./MyLazyComponent'))
    
    function App() {
      const [showComponent, setShowComponent] = useState(false)
      return (
        <>
          

    Lazy component example

    Loading component...
    }> {showComponent && } ); } export default App

    在我们的 `App.jsx` 文件中,我们实例化了一个 `LazyComponent` 变量,该变量使用 `React.lazy()` 函数动态调用我们之前创建的 `MyLazyComponent`。我们有一个 `showComponent` 状态,该状态初始化为 false,并在单击按钮时设置为 true。一旦 `showComponent` 的状态设置为 true,`MyLazyComponent` 就会加载到页面上。内置的 `Suspense` 组件为 `MyLazyComponent` 正在加载时提供了一个后备 UI。

    如果按照原样使用代码,我们看不到 fallback UI 的效果,因为惰性加载组件加载得太快了。让我们模拟一下惰性加载组件的延迟。通过使用 promise,我们可以使用 `setTimeout` 函数来引发两秒的延迟。我们在这里使用 promise 是因为我们正在使用动态导入:

    const LazyComponent = React.lazy(
      () =>
        new Promise((resolve) => {
          setTimeout(() => resolve(import("./MyLazyComponent")), 2000);
        })
    );

    运行上述修改后的代码,你现在可以看到 fallback UI 在惰性组件加载并显示在页面上时就生效了:

    然而,值得注意的是,即使没有 `React.lazy` 函数,我们也能运行并看到相同的结果。然而,这违背了延迟加载的目的,因为组件仍在后台加载。`React.lazy` 至关重要,因为它允许我们动态导入组件并仅在需要时使用它,而无需将其包含在初始应用程序包中。这就是延迟加载的全部意义所在。没有 `React.lazy`,`MyLazyComponent` 仍包含在初始应用程序包中。

    React 中的预加载

    预加载是 React 中加载组件的默认行为,可以通过 `[useEffect](https://blog.logrocket.com/useeffect-react-hook-complete-guide/)` Hook 或普通组件导入来实现。如果我们必须重构上面的代码来演示预加载,我们会这样做。

    我们将 `MyLazyComponent` 重构为 `MyEagerComponent`:

    const MyEagerComponent = () => {
      return (
        

    I am an eager-loaded component, hello.

    ) } export default MyEagerComponent

    至于我们的 `App.jsx`:

    import MyEagerComponent from "./MyEagerComponent";
    
    function App() {
    
      return (
        <>
          

    Eager component example

    ); } export default App

    您可以看到,无需额外的代码即可即时加载上述组件。运行此应用程序会立即将即时组件加载到页面上。

    结论

    在本文中,我们详细探讨了即时加载和延迟加载,介绍了它们的优点和区别。我们还在 React 等单页应用程序中仅使用组件实现了延迟加载和即时加载。

    这些技术对于优化 Web 应用程序的性能至关重要。延迟加载有助于通过减少初始加载时间和节省带宽来增强用户体验,使其成为不经常访问的数据的理想选择。另一方面,预先加载可确保数据一致性并简化代码,特别是在应用程序不同部分需要数据的情况下。通过选择正确的加载策略,您可以显著提高应用程序的响应能力和性能,最终为用户创造更无缝的体验。

    几分钟内即可设置 LogRocket 的现代错误跟踪:

  • 访问 https://logrocket.com/signup/ 获取应用程序 ID。
  • 通过 NPM 或脚本标签安装 LogRocket。LogRocket.init() 必须在客户端调用,而不是服务器端。
  • 新版本:

    $ npm i --save logrocket 
    
    // Code:
    
    import LogRocket from 'logrocket'; 
    LogRocket.init('app/id');

    脚本标记:

    Add to your HTML:
    
    
    

    3.(可选)安装插件以便与您的堆栈进行更深入的集成:

  • Redux 中间件
  • ngrx 中间件
  • Vuex 插件
  • 现在就开始。