增量更新是目前大部分團隊採用的快取更新方案,能讓使用者在無感知的情況獲取最新內容。具體實現方式通常是(一般我們通過構建工具來實現,比如webpack
):
- 構建產出檔案hash(如:
index.d94f83fac22c203b788c.css
) - 更新
html
檔案裡靜態資源的引用URL
由於其他資源是由html檔案直接或間接引用才可以被載入,如果html裡的靜態資源URL更新了,那請求的肯定就是最新資源了。那我們需要考慮的就是如何確保載入的html是最新的了,其他的靜態資源就充分利用瀏覽器快取以減少網路請求提高web效能。瀏覽器快取實質就是HTTP快取,而HTTP快取分為強快取
和協商快取
。
強快取
強快取不會傳送請求,直接從瀏覽器載入資源。是否命中強快取根據HTTP Response頭部Expires
、Cache-Control
(max-age
)來判斷。
-
Expires
通過返回一個過期時間來判斷是否過期,在此時間之前瀏覽器直接從快取載入資源。但其缺點是返回的過期時間為伺服器時間,而比較是同客戶端時間比較,如果服務端和客戶端存在時間誤差就不準了。 -
max-age
返回的時間過期時間跨度,比如max-age=3600告訴瀏覽器接下來的1小時內使用快取。這樣就解決了Expires
時間誤差導致的問題。
強快取命中優先判斷max-age
,max-age
優先順序大於Expires
,判斷流程如下:
協商快取
-
Etag
和If-None-Match
Etag的值是根據一定演算法生成的字串,用以判斷檔案是否更改,類似於檔案hash。在第一次訪問時,服務會返回該檔案的Etag值,在之後的訪問通過在請求頭增加If-None-Match引數,把Etag的值帶過去,伺服器通過比較Etag的值來判斷是否需要重新返回最新資源(200 or 304)。 -
Last-Modified
和If-Modified-Since
Last-Modified為該資原始檔的最後修改時間。同樣在第一次返回,之後通過If-Modified-Since帶過去,伺服器通過比較值來判斷是否需要返回最新資源。
如果 If-None-Match
和 If-Modified-Since
都有,則必須一次性都發給伺服器,沒有優先順序,實際中比較ETag
就夠了。如果請求頭裡沒有,則每次都會返回最新的資源200
快取判斷流程
為了確保html每次都是最新的,我們這裡不能使用強快取。可以在伺服器(nginx、tomact)設定訪問html檔案時Cache-Control為no-cache
。(這個需要在伺服器配合設定,前端是處理不了的)