使用 IndexedDB 持續保留應用程式狀態的最佳做法

瞭解在 IndexedDB 和熱門狀態管理程式庫之間同步應用程式狀態的最佳做法。

使用者初次載入網站或應用程式時,建構用來轉譯 UI 的初始應用程式狀態通常需要大量工作。舉例來說,有時應用程式需要在用戶端驗證使用者,然後發出數個 API 要求,才能取得所需的所有資料,在頁面上顯示。

將應用程式狀態儲存在 IndexedDB 中,是加快重複造訪載入時間的絕佳方法。接著,應用程式就能在背景同步處理任何 API 服務,並以「stale-while-revalidate」策略,以非同步方式更新 UI 中的新資料。

不過,使用 IndexedDB 時,有許多重要事項需要考量,這些事項對新手開發人員來說可能不太明顯。本文件將回答常見問題,並討論在 IndexedDB 中保留應用程式狀態時,應留意的一些重要事項。

讓應用程式提供可預測的體驗

IndexedDB 的許多複雜性,源自於開發人員無法控制的許多因素。本節將探討使用 IndexedDB 時必須留意的許多問題。

無法寫入儲存空間

寫入 IndexedDB 時可能會發生錯誤,原因有很多種,在某些情況下,這些原因超出開發人員的控制範圍。舉例來說,某些瀏覽器不允許在私密瀏覽模式下寫入 IndexedDB。使用者的裝置磁碟空間可能快用完,瀏覽器就會限制使用者無法儲存任何內容。

因此,請務必在 IndexedDB 程式碼中實作適當的錯誤處理機制。這也表示,除了儲存應用程式狀態之外,通常將狀態保留在記憶體中也是不錯的做法,這樣一來,即使在私人瀏覽模式下執行或無法使用儲存空間,使用者介面也不會中斷 (即使某些需要儲存空間的其他應用程式功能無法運作也是如此)。

儲存的資料可能已遭使用者修改或刪除

有別於伺服器端資料庫,您可以限制未經授權的存取,而用戶端資料庫則可供瀏覽器擴充功能和開發人員工具存取,而且使用者可以清除這些資料庫。

雖然使用者很少修改本機儲存的資料,但清除資料則是常見的操作。您必須讓應用程式能夠處理這兩種情況,而不會發生錯誤。

儲存的資料可能已過時

與上一節所述類似,即使使用者未自行修改資料,他們儲存的資料也可能是由舊版程式碼 (可能含有錯誤) 寫入。

IndexedDB 內建對結構定義版本的支援,並使用其 IDBOpenDBRequest.onupgradeneeded() 方法升級;但您仍需撰寫升級程式碼,以便處理來自先前版本的使用者 (包括含有錯誤的版本)。

單元測試在此處相當實用,因為通常無法手動測試所有可能的升級路徑和案例。

確保應用程式效能良好

IndexedDB 的其中一項主要功能是非同步 API,但別讓人誤以為自己在使用時不會擔心效能問題。在某些情況下,不當使用行為仍會封鎖主執行緒,進而導致沒有回應。

一般來說,對 IndexedDB 的讀取和寫入作業不應超過存取資料所需的大小。

雖然 IndexedDB 可將大型巢狀物件儲存為單一記錄 (從開發人員的角度來看,這麼做確實相當方便),但不建議採用這種做法。這是因為 IndexedDB 儲存物件時,必須先建立該物件的結構化複本,而結構化複製程序會在主執行緒上執行。物件越大,封鎖時間越長。

這在規劃如何將應用程式狀態保留至 IndexedDB 時帶來一些挑戰,因為大多數常用的狀態管理程式庫 (例如 Redux) 都能透過單一 JavaScript 物件來管理整個狀態樹狀結構。

雖然以這種方式管理狀態有許多好處,雖然在 IndexedDB 中將整個狀態樹狀結構儲存為單一記錄,這可能既誘人又方便,但在每次變更後進行這項操作 (即使受到節流/去彈跳動) 會導致主執行緒不必要的封鎖,但有時也會增加寫入錯誤的可能性,甚至造成瀏覽器無回應。

請將整個狀態樹狀圖分割成個別記錄,並只更新實際變更的記錄,而非將整個狀態樹狀圖儲存在單一記錄中。

如同大多數最佳做法,這並不是萬無一失的規則。如果無法分割狀態物件並只寫入最低的變更集,請將資料分解成子樹狀結構,且只寫入整個狀態樹狀結構仍傾向寫入整個狀態樹狀結構。小幅改善比任何都沒有改善。

最後,您一律應評估所寫程式碼的效能影響。雖然對索引資料庫進行少量寫入作業的執行成效優於大型寫入作業,但只有在應用程式確實執行的 IndexedDB 寫入作業確實導致主執行緒封鎖主執行緒,進而破壞使用者體驗時,才很重要。請務必進行評估,以便瞭解要最佳化的項目。

結論

開發人員可以使用 IndexedDB 等用戶端儲存機制,讓不同的工作階段保持狀態,並減少重複造訪時載入初始狀態所需的時間,進而改善應用程式的使用者體驗。

正確使用 IndexedDB 可以大幅提升使用者體驗,但若使用錯誤或未能處理錯誤情況,可能會導致應用程式損毀和使用者感到不滿。

由於用戶端儲存空間涉及許多您無法控制的因素,因此務必確保程式碼經過充分測試,並能妥善處理錯誤,即使這些錯誤一開始看起來不太可能發生也一樣。