使用 React.lazy 和 Suspense 分割程式碼

您不需要為使用者提供超過需要的程式碼,因此請分割您的套裝組合,確保這種情況不會發生!

React.lazy 方法可讓您輕鬆使用程式碼分割 使用動態匯入功能處理元件層級

import React, { lazy } from 'react';

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

const DetailsComponent = () => (
  <div>
    <AvatarComponent />
  </div>
)

這種報表有哪些優點?

大型 React 應用程式通常包含許多元件、公用程式 方法和第三方程式庫如果不嘗試載入 因此,只在必要時呈現應用程式的所有不同部分 當使用者載入 JavaScript 套件, 第一頁這會大幅影響網頁效能。

React.lazy 函式提供內建方法來區分 將應用程式分成不同的 JavaScript 區塊,且幾乎不會執行任何工作你可以 然後處理載入狀態和 Suspense 元件。

Suspense (懸疑)

向使用者傳送大型 JavaScript 酬載的問題為 網頁完成載入所需的時間 和網路連線這就是程式碼分割和延遲載入 非常有幫助

然而,當使用者執行這項作業時 系統正在透過網路擷取程式碼分割元件 會顯示實用的載入狀態搭配 Suspense 使用 React.lazy 可協助解決這個問題

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

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

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
  </Suspense>
)

Suspense 接受可讓您顯示任何 React 的 fallback 元件 視為載入狀態以下範例說明運作方式。 只有在使用者點選按鈕時,顯示圖片才會顯示 然後加以擷取,為已暫停的 AvatarComponent 擷取必要程式碼。 在此期間,系統會顯示備用載入元件。

在這裡,組成 AvatarComponent 的程式碼很小 為何載入旋轉圖示只顯示一小段時間較大 可能需要較長的時間才能載入 網路連線不穩

以下將進一步說明運作方式:

  • 如要預覽網站,請按下「查看應用程式」。然後按下 全螢幕 全螢幕
  • 按下 Control+Shift+J 鍵 (或在 Mac 上為 Command+Option+J 鍵) 開啟開發人員工具。
  • 按一下 [網路] 分頁標籤。
  • 按一下「Throttling」下拉式選單 (預設為「無節流」)。選取「Fast 3G」
  • 按一下應用程式中的「Click Me」按鈕。

載入指標會一直持續顯示。請注意 構成 AvatarComponent 的構成元素是獨立區塊。

開發人員工具網路面板,顯示正在下載的 chunk.js 檔案

暫停多個元件

Suspense 的另一項功能是可讓您暫停多項 載入元件時,「即使所有元件都是延遲載入」

例如:

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

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
    <InfoComponent />
    <MoreInfoComponent />
  </Suspense>
)

如果您想延遲多個元件的轉譯作業, 只顯示單一載入狀態所有元件都完成了 使用者看到這些內容時就會同時顯示全部

您可以透過下列內嵌內容查看這項資訊:

如未經過這個設計,就很容易遇到停滯載入問題;或 UI 的不同部分會逐一載入 正在載入指標這樣會讓使用者感覺更不耐煩。

處理載入失敗

Suspense 可讓您在網路連線時顯示暫存載入狀態 處理要求不過,如果網路要求失敗 什麼原因呢?可能是已離線,或是網頁應用程式正在嘗試 延遲載入版本化網址

React 具備標準模式,可妥善處理這些類型的載入作業 失敗:使用錯誤邊界如說明文件所述, 只要是實作的 React 元件,都可以做為錯誤邊界 (或 包括生命週期方法的 static getDerivedStateFromError()componentDidCatch()

如要偵測並處理延遲載入失敗的問題,您可以包裝 Suspense 元件,並將父項元件設為錯誤邊界。內部 錯誤邊界的 render() 方法,若有 沒有錯誤,若發生問題,則顯示自訂錯誤訊息:

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

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {hasError: false};
  }

  static getDerivedStateFromError(error) {
    return {hasError: true};
  }

  render() {
    if (this.state.hasError) {
      return <p>Loading failed! Please reload.</p>;
    }

    return this.props.children;
  }
}

const DetailsComponent = () => (
  <ErrorBoundary>
    <Suspense fallback={renderLoader()}>
      <AvatarComponent />
      <InfoComponent />
      <MoreInfoComponent />
    </Suspense>
  </ErrorBoundary>
)

結論

不確定要從何處開始將程式碼分割至 React 應用程式,請按照下列步驟操作:

  1. 從路線層級開始。路徑是找出 以便分割應用程式 React 文件 展示如何搭配運用 Suspense react-router
  2. 找出網站中只在特定情況下顯示的大型元件 特定使用者互動情形 (例如按下按鈕) 來放送廣告。拆分流量 元件,可將 JavaScript 酬載降到最低。
  3. 建議分割在畫面外的任何其他項目,對 內容。