自信使用 React.lazy:當快速迭代時安全加載組件的方法
React.lazy 是一種根據需要加載組件並提高應用性能的絕佳方式。然而,有時它可能會導致一些問題,例如「ChunkLoadError」和「加載塊失敗」。
困境
如今,軟體開發在流行的「快速行動並打破常規」的哲學下更快地推進。在這裡不做評價——事情就是這樣。然而,這種快節奏有時會導致問題,特別是在用 React 加載組件時。
如果你正在一個使用 React.lazy 來根據需要加載組件的專案,你可能遇到過像 ChunkLoadError
和「加載塊失敗」這樣的問題。以下是一些可能的原因:
- 存在網絡問題,例如,用戶的互聯網連接緩慢或不穩定。
- 用戶的應用版本過時,瀏覽器正在嘗試加載已經不存在的塊。
通常,簡單刷新頁面可以解決問題,但這對用戶來說不是最佳體驗。想像一下,當用戶導航到另一個路由時出現白屏——這對你的應用來說不好看。
我們能在速度需求與流暢用戶體驗之間取得平衡嗎?當然。讓我告訴你方法(當然是用 TypeScript)。
解決方案
一個粗暴的解決方案是將所有版本的塊保存在服務器中,這樣就不會出現「缺失塊」問題。隨著應用的增長,這種解決方案可能因磁碟空間需求增加而變得不可行,並且它仍然無法解決網絡問題。
鑑於重試或刷新可以解決問題,我們可以在代碼中實施這些解決方案。鑒於問題通常發生在用戶導航至另一個路由時,我們甚至可以在用戶不注意的情況下解決它。我們所需要做的只是構建一個包裹函數來包裹 React.lazy
,以便處理重試和刷新。
已經有一些很好的文章介紹如何實現這種解決方案,因此我將重點放在該解決方案的思路和內部運作上。
創建包裹函數
第一步是創建一個包裹 React.lazy
函數的包裹函數:
處理重試
對於網絡問題,我們可以通過將 importFunction
包裹在 tryImport
函數中來處理重試:
看起來很簡單吧?你還可以實現 指數退避 演算法來更有效地處理重試。
處理刷新
對於過時版本問題,我們可以通過捕捉錯誤並刷新頁面來處理刷新:
然而,這種實現非常危險,因為當錯誤無法通過刷新解決時可能導致無限刷新循環。同時,應用狀態將在刷新過程中丟失。因此我們需要 sessionStorage
的幫助來存儲我們已經嘗試刷新頁面的消息:
現在,當我們從 safeLazy
函數中捕捉錯誤時,我們知道這是一些刷新無法解決的問題。
同一頁面上的多個懶加載組件
目前的實現中仍有一個潛在的陷阱。如果你在同一頁面上有多個懶加載組件,無限刷新循環仍可能發生,因為其他組件可能會重置 sessionStorage
值。為了解決這個問題,我們可以為每個組件使用一個唯一鍵:
現在,每個組件都將擁有自己的 sessionStorage
密鑰,將避免無限刷新循環。我們可以繼續苛求解決方案,例如:
- 將所有鍵集中在一個數組中,因此只需一個存儲鍵。
- 設置刷新限制以便在拋出錯誤前重複刷新頁面多次。
但我認為你明白這個想法。一個完整的 TypeScript 解決方案以及測試和配置可在 GitHub 儲存庫 中找到。我還在 NPM 上發佈了 react-safe-lazy
包,所以你可以立即在你的專案中使用它。
結論
軟體開發是一項細緻的工作,即便是最小的細節也可能需要努力去解決。我希望這篇文章能幫助你優雅地處理 React.lazy
的問題,並改善你的應用的用戶體驗。