您不需要向使用者提供比必要更多的程式碼,因此請分割套件,確保不會發生這種情況!
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 酬載的問題,是網頁完成載入所需的時間長度,特別是在效能較差的裝置和網路連線上。因此,程式碼分割和延遲載入非常實用。
不過,透過網路擷取程式碼分割元件時,使用者一律會遇到些微的延遲,因此顯示實用的載入狀態十分重要。搭配 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
會接受 fallback
元件,讓您將任何 React 元件顯示為載入狀態。以下範例說明這項機制的運作方式。只有在按下按鈕時才會顯示顯示圖片,並且會提出要求,以便擷取暫停的 AvatarComponent
所需的程式碼。在此期間,系統會顯示備用載入元件。
在這裡,構成 AvatarComponent
的程式碼很小,因此載入旋轉圖示只會顯示一段短時間。較大的元件可能需要更長的時間才能載入,尤其是在網路連線不佳的情況下。
以下將進一步說明運作方式:
- 如要預覽網站,請按下「View App」,然後按下「Fullscreen」。
- 按下 `Control+Shift+J` 鍵 (在 Mac 上為 `Command+Option+J` 鍵) 開啟開發人員工具。
- 按一下 [網路] 分頁標籤。
- 點選「Throttling」下拉式選單,預設值為「No throttling」。選取「快速 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 酬載。
- 請考慮將畫面外且對使用者不重要的任何內容分割。