您只需要為使用者提供多餘的程式碼,
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 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。
- 點選「Throttling」下拉式選單,預設設定為「無節流」。選取「Fast 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 應用程式,請按照下列步驟操作:
- 從路線層級開始。路徑是識別可以分割的應用程式點最簡單的方法。如要瞭解如何搭配使用
Suspense
與react-router
,請參閱 React 文件。 - 找出網站上只有特定使用者互動 (例如點選按鈕) 才會顯示的大型元件。分割這些元件可盡量減少 JavaScript 酬載。
- 請考慮分割畫面外且對使用者來說不重要的其他項目。