PWA筆記一:Web的萬物基礎緩存

前言

這里討論的緩存包括兩種,一種是HTTP緩存,一種是Service Worker緩存。

HTTP緩存

HTTP緩存應該是最傳統的方式,也是所有前端項目的基礎。瀏覽器向服務器請求數據,發送請求(request)報文;服務器向瀏覽器返回數據,返回響應(response)報文。我們熟悉的瀏覽器緩存機制可以被分為兩大類:強緩存和協商緩存。強緩存主要包括Cache-Control和Expires,協商緩存主要包括Etag和Last-Modify。協商緩存優先級是優先于強緩存。js等大部分靜態資源在做了文件指紋后,都使用強緩存的策略。而html文件是頁面入口和文件名不能修改比較特殊,大部分都采用協商緩存。

強緩存

Cache-Control

一般js,css和圖片等靜態資源文件采用強緩存的機制,保證資源在某個時間段內在命中的情況下從緩存機制中獲取。

稍微了解HTTP協議的前端同學,想必對Cache-Control不會感到陌生,性能優化時經常都會跟它打交道,屬于HTTP 1.1。常見的值有有private、public、no-store、no-cache、must-revalidate、max-age等。

強緩存
  • no-cache: 不管本地副本是否過期,使用資源副本前,強制回源服務器進行副本有效性校驗。
  • must-revalidate:本地副本過期前可以使用本地副本;本地副本一旦過期,必須去源服務器進行有效性校驗。

Expires

Expires的值為服務端返回的到期時間,即下一次請求時,請求時間小于服務端返回的到期時間,直接使用緩存數據。這樣會帶來一個問題,就是服務器時間和客戶端時間不一致的情況,現在網頁都是全球化的,會造成不同時區的用戶訪問更新不一致。Expires 是HTTP 1.0的東西,現在默認瀏覽器均默認使用HTTP 1.1。

協商緩存

Etag

協商緩存(又名對比緩存)由服務器來確定緩存資源是否可用,所以客戶端與服務器端要通過某種標識來進行通信,從而讓服務器判斷請求資源是否可以緩存訪問。而Etag就是這個標示,屬于HTTP1.1的標準。如果命中協商緩存會返回304,如果未命中會從服務器取數據返回200。它和Last-Modify最大的區別就是,Last-Modify專注某個時間點。這個和Expires犯了同樣的錯誤。協商緩存整個流程如下圖,它必須和服務器有一次交互,一般html的檢查是否更新,就是這樣完成。一般像JS和CSS都是帶hash值,保證文件唯一性,控制緩存。

協商緩存

為什么需要Etag?

  • 一些文件也許會周期性的更改,但是他的內容并不改變(僅僅改變的修改時間),這個時候我們并不希望客戶端認為這個文件被修改了,而重新GET;
  • 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
  • 某些服務器不能精確的得到文件的最后修改時間。

如果你使用協商緩存,第一次加載返回200狀態碼,加載速度較慢,數據量大。第二次加載返回304狀態碼,加載速度較快,數據量小。這也是為什么我們第二次加載速度比較快,第一次加載比較慢。此外,協商緩存和網速有強相關性,網速慢的情況下,頁面加載速度也會很慢。

緩存情況

Last-Modify

Last-Modify記錄的是指上次代碼更新的時間。上次更新的時間和客戶端當前時間的對比,決定了協商緩存是否執行。

強緩存和協商緩存的對比

強緩存和協商緩存其實都是為了解決非首次加載后的緩存問題。協商緩存可以保證渠道的靜態資源是最新內容。

緩存類型 狀態碼 發送請求到服務器
強緩存 200(from cache) 否,直接從緩存取
協商緩存 304(Not Modified) 否,通過服務器來告知緩存是否可用
用戶操作 Expires/Cache-Control Last-Modied/Etag
地址欄回車 有效 有效
頁面鏈接跳轉 有效 有效
新開窗口 有效 有效
前進回退 有效 有效
F5刷新 無效 有效
Ctrl+F5強制刷新 無效 無效

在實際使用的過程當中,緩存的策略可以通過nginx或者cdn運營商配置對應的緩存策略。如今應該各種大廠都有自建cdn來達到靜態資源加速的效果。

Service Worker緩存

但是HTTP的緩存每次生效嗎?在app強制關閉的情況下能控制緩存機制嗎?在弱網的情況下,協商緩存會和后端進行交互,還是影響頁面白屏時間。Service Worker緩存(簡稱SW緩存)就是用解決協商緩存的問題,并且給開發者提供了控制緩存的能力。如果你做的網頁可以被當成一個大型單頁面應用,這個應用需要一個manifest.json來控制它基礎應用顯示信息,還需要以一個service-worker.js來控制它的離線緩存信息。

HTTP以前的緩存機制是Network和application之間的交互,Service Worker緩存機制則是在它們之間加入一個代理層,優先取本地的資源,之后檢查數據內容是否更新。如果有更新,將會在下一次更新才更新數據內容。

因此,SW緩存也是pwa的基礎要素之一,詳情可見PWA筆記二:離線緩存原理

代理層

WIFI 情況

From SW DomLoaded 571ms Load 1.41s
From Cache DomLoaded 593ms Load 1.12s

3G情況

From SW DomLoaded 572ms Load 4.46s
From Cache DomLoaded 10.37ms Load 10.69s

在網速弱網情況,協商緩存的情況會收到影響,因為它和網速是強相關的。而service-worker和網速時弱相關的,和單頁面網頁應用的屬性是天然契合的,幫助網頁應用更貼近native app。

參考

PS

shopee,又稱蝦皮,是一家騰訊投資的跨境電商平臺。這里加班少,技術氛圍好。如果想和我并肩作戰一起學習,可以找我內推。郵箱1542453460@qq.com,非誠勿擾。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容