工程化——前端靜態資源快取策略

weixin_33806914發表於2019-03-01

增量更新是目前大部分團隊採用的快取更新方案,能讓使用者在無感知的情況獲取最新內容。具體實現方式通常是(一般我們通過構建工具來實現,比如webpack):

  • 構建產出檔案hash(如:index.d94f83fac22c203b788c.css)
  • 更新html檔案裡靜態資源的引用URL

由於其他資源是由html檔案直接或間接引用才可以被載入,如果html裡的靜態資源URL更新了,那請求的肯定就是最新資源了。那我們需要考慮的就是如何確保載入的html是最新的了,其他的靜態資源就充分利用瀏覽器快取以減少網路請求提高web效能。瀏覽器快取實質就是HTTP快取,而HTTP快取分為強快取協商快取

強快取

強快取不會傳送請求,直接從瀏覽器載入資源。是否命中強快取根據HTTP Response頭部ExpiresCache-Controlmax-age)來判斷。

  • Expires通過返回一個過期時間來判斷是否過期,在此時間之前瀏覽器直接從快取載入資源。但其缺點是返回的過期時間為伺服器時間,而比較是同客戶端時間比較,如果服務端和客戶端存在時間誤差就不準了。
  • max-age返回的時間過期時間跨度,比如max-age=3600告訴瀏覽器接下來的1小時內使用快取。這樣就解決了Expires時間誤差導致的問題。

強快取命中優先判斷max-agemax-age優先順序大於Expires,判斷流程如下:
clipboard.png

協商快取

  • EtagIf-None-Match Etag的值是根據一定演算法生成的字串,用以判斷檔案是否更改,類似於檔案hash。在第一次訪問時,服務會返回該檔案的Etag值,在之後的訪問通過在請求頭增加If-None-Match引數,把Etag的值帶過去,伺服器通過比較Etag的值來判斷是否需要重新返回最新資源(200 or 304)。
  • Last-ModifiedIf-Modified-Since Last-Modified為該資原始檔的最後修改時間。同樣在第一次返回,之後通過If-Modified-Since帶過去,伺服器通過比較值來判斷是否需要返回最新資源。

如果 If-None-MatchIf-Modified-Since 都有,則必須一次性都發給伺服器,沒有優先順序,實際中比較ETag就夠了。如果請求頭裡沒有,則每次都會返回最新的資源200

快取判斷流程

clipboard.png

為了確保html每次都是最新的,我們這裡不能使用強快取。可以在伺服器(nginx、tomact)設定訪問html檔案時Cache-Control為no-cache。(這個需要在伺服器配合設定,前端是處理不了的)

相關文章