The #ChromeDevSummit site is live, happening Nov 12-13 in San Francisco, CA
Check it out for details and request an invite. We'll be diving deep into modern web tech & looking ahead to the platform's future.

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 以及之前致力於網絡存儲空間的其他人。