Missed the action at the 2018 Chrome Dev Summit? Catch up with our playlist on the Google Chrome Developers channel on YouTube. Watch now.

Progressive Web App 的離線存儲

DevTools 中的 PWA
Pokedex Progressive Web App 針對應用狀態和 Pokemon 數據集使用 IndexedDB,而對於網址可尋址的資源則使用 Cache API。

在路上時互聯網連接會變得不穩定或無法上網,這是離線支持和可靠的性能成爲 Progressive Web App 中的常用功能的原因。即使在完美的無線環境中,明智地使用緩存和其他存儲技術也可顯著改善用戶體驗。在此博文中,我們將圍繞 PWA  的離線數據存儲總結一些想法—思考提供有效的離線體驗所需的 JSON 負載、圖像和常規靜態數據。

建議:

我們進入正題,首先介紹針對離線存儲數據的建議:

下面介紹基本原理:

上述兩個 API 都是異步的(IndexedDB 基於事件的,而 Cache API 基於 Promise)。 它們也使用網頁工作線程、窗口和服務工作線程。 IndexedDB 在每個位置都可用。 服務工作線程(和 Cache API)目前在 Chrome、Firefox、Opera 中可用,並正在針對 Edge 進行開發。IndexedDB 的 Promise 包裝器隱藏了 IndexedDB 庫自帶的一些強大但同時也非常複雜的 machinery(例如,事務處理、架構版本)。IndexedDB 將支持 observers,其讓您可以輕鬆實現標籤之間的同步。

Safari 10 在其最新的技術預覽版中修復了許多長期存在的 IndexedDB 錯誤。Note: 一些用戶發現 Safari 10 的 IndexedDB 和 PouchDB 存在穩定性問題,並發現其速度有些慢。在對此問題進行更多研究之前,您的情況可能有所不同。請進行測試並提交瀏覽器錯誤,以便 @webkit 工作任意和相關的 OSS 庫作者可以查看。默認情況下,LocalForage、PouchDB、YDN 和 Lovefield 在 Safari 中使用 WebSQL(因爲缺少有效的方法對損壞的 IndexedDB 進行功能測試)。這意味着這些庫無需任何額外操作即可在 Safari 10 中使用(只是不直接使用 IndexedDB)。

對於 PWA,您可以緩存靜態資源,從而使用 Cache API 編寫您的應用 Application Shell(JS/CSS/HTML 文件),並從 IndexedDB 填充離線頁面數據。

針對 IndexedDB 的調試支持目前在 Chrome(Application 標籤)、Opera、Firefox(Storage Inspector) 和 Safari(請參閱 Storage 標籤)中可用。

其他存儲機制是怎樣的?

Web Storage(例如 LocalStorage 和 SessionStorage)是同步的,不支持網頁工作線程,並對大小和類型(僅限字符串)進行限制。 Cookie 具有自身的用途,但它們是同步的,缺少網頁工作線程支持,同時對大小進行限制。WebSQL 不具有廣泛的瀏覽器支持,因此不建議使用它。File System API 在 Chrome 以外的任意瀏覽器上都不受支持。目前正在 File and Directory Entries APIFile API 規範中改進 File API,但該 API 還不夠成熟也未完全標準化,因此無法被廣泛採用。

我能存儲多少數據?

瀏覽器 限制
Chrome 可用空間 <6%
Firebox 可用空間 <10%
Safari <50MB
IE10 <250MB

在 Chrome 和 Opera 中,按照源(而不是 API)進行存儲。這兩個存儲機制都將存儲數據,直到達到瀏覽器配額。應用可以使用 Quota Management API 檢查它們目前使用了多少配額。 在 Chrome 中,應用最多可使用 6% 的磁盤空間。在 Firefox 中,應用最多可使用 10% 的可用磁盤空間,但在存儲 50MB 數據後將提示用戶進行更多存儲請求。 在 Mobile Safari 中,應用最多可使用 50MB 存儲空間,而 Safari 桌面版不限制存儲空間的使用(並在達到 5MB 後進行提示)。IE10+ 最多可存儲 250MB,並在存儲 10MB 後提示用戶。 PouchDB 跟蹤 IDB 存儲行爲。

如何瞭解我的應用目前使用了多少存儲空間?

在 Chrome 中,您可以使用 Quota Management API 查詢目前使用的存儲空間大小,以及應用可使用多少空間。更新的 Storage Quota Estimate API 嘗試通過支持 Promise,讓用戶更容易瞭解源目前使用了多少配額。

緩存逐出是如何工作的?

瀏覽器 逐出政策
Chrome 在 Chrome 耗盡空間後採用 LRU 策略
Firebox 在整個磁盤已裝滿時採用 LRU 策略
Safari 無逐出
Edge 無逐出

根據源的需求爲源提供空間量。此可用空間在所有形式的源存儲(IndexedDB、Cache API、localStorage 等)中共享。提供的空間量未指定,具體容量因設備和存儲條件而異。

如果網絡存儲容量低,則 UA 將清除存儲以提供可用的空間。這會損害離線響應能力,因此,最近更新的存儲規範定義了“持久化”和“盡力而爲”策略,默認策略是“盡力而爲”。“盡力而爲”指的是在不干擾用戶的情況下可以清除存儲,但對於長期和/或關鍵數據而言持久性較差。IndexedDB 和 Cache API 目前都屬於“盡力而爲”類別。

“持久化”存儲在存儲容量低時不會自動清除。用戶需要手動清除此存儲(通過瀏覽器設置)。 Chrome 一直在來源試用版中試驗對持久化存儲的支持,最新消息表明將在 Chrome 55 中發佈對持久化存儲的支持。

當前和未來的離線存儲運行

如果您對離線存儲感興趣,則要注意下面取得的成就。

離線存儲並沒有多神奇,瞭解底層 API 對您大有幫助,讓您可充分利用我們現在提供的 API。無論您是否願意直接使用這些 API 還是使用一個抽象庫,都需要花些時間熟悉您的選項。

希望本指南將幫助您設計一個離線體驗,讓您的 PWA 大放光彩!✨

背景閱讀

實用資源

  • sw-toolbox(針對動態/運行時請求的離線緩存)

  • sw-precache(針對靜態資產/Application Shell 的離線預緩存

  • Webpack 用戶可以直接使用上面的資源或 offline-plugin

值得關注的 IndexedDB 庫

在此我要感謝 Nolan Lawson、Joshua Bell (這篇文章的主要靈感來自於他在 Open Web Storage 方面的工作和 BlinkOn 演講)、Jake Archibald、Dru Knox 以及之前致力於網絡存儲空間的其他人。