您絕不需要向使用者傳送超出必要的程式碼,因此請分割套件,確保絕不會發生這種情況!
React.lazy
方法可讓您使用動態匯入功能,輕鬆在元件層級程式碼分割 React 應用程式。
import React, { lazy } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const DetailsComponent = () => (
<div>
<AvatarComponent />
</div>
)
這種報表有哪些優點?
大型 React 應用程式通常包含許多元件、公用程式方法和第三方程式庫。如果沒有在需要時才載入應用程式的不同部分,系統會在使用者載入第一頁時,將單一的大型 JavaScript 套件傳送給他們。這可能會大幅影響網頁效能。
React.lazy
函式提供內建方式,可將應用程式中的元件分成不同的 JavaScript 區塊,幾乎不需要額外作業。然後,您可以將其與 Suspense
元件配對,處理載入狀態。
Suspense (懸疑)
向使用者傳送大量 JavaScript 酬載的問題在於,網頁完成載入所需的時間會很長,尤其是在效能較弱的裝置和網路連線中。因此,程式碼分割和延遲載入非常實用。
不過,透過網路擷取程式碼分割元件時,使用者一定會遇到些許延遲,因此請務必顯示實用的載入狀態。使用 React.lazy
元件搭配 Suspense
即可解決這個問題。
import React, { lazy, Suspense } from 'react';
const AvatarComponent = lazy(() => import('./AvatarComponent'));
const renderLoader = () => <p>Loading</p>;
const DetailsComponent = () => (
<Suspense fallback={renderLoader()}>
<AvatarComponent />
</Suspense>
)
Suspense
接受 fallback
元件,可讓您將任何 React 元件顯示為載入狀態。以下範例說明運作方式。
只有在點選按鈕時,系統才會算繪虛擬人偶,並發出要求,擷取暫停 AvatarComponent
所需的程式碼。在此期間,系統會顯示備用載入元件。
這裡的 AvatarComponent
程式碼很小,因此載入微調器只會顯示一小段時間。較大的元件可能需要較長時間載入,尤其是在網路連線不穩定的情況下。
為進一步說明運作方式,請參考以下範例:
- 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示
。
- 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。
- 按一下「節流」下拉式選單 (預設為「不節流」),選取「快速 3G」。
- 按一下應用程式中的「Click Me」按鈕。
載入指標現在會顯示較長時間。請注意,構成 AvatarComponent
的所有程式碼都會以個別區塊的形式擷取。

暫停多個元件
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 應用程式,請按照下列步驟操作:
- 從路線層級開始。路徑是識別應用程式可分割點的最簡單方式。請參閱 React 文件,瞭解如何搭配使用
Suspense
和react-router
。 - 找出網站頁面上僅在特定使用者互動 (例如點選按鈕) 時才會顯示的大型元件。分割這些元件可盡量減少 JavaScript 酬載。
- 如果其他內容不在螢幕上,且對使用者來說不重要,建議您將其分割。