推薦閲讀:
- 2020年軟件開發趨勢
- 高併發案例 - 庫存超發問題
- 負載均衡的分類及算法
- 異地多活架構
- Postman 的替代品來了
有時,當第二次訪問網站時,看起來比較怪,樣式不正常。
通常,是因為 cache control 緩存控制策略定義不正確,導致服務端最新部署之後客户端沒有接收到最新的更改。
本文將向您展示正確的緩存設置,以便在每次部署後使所有用户的網站保持最新狀態。
緩存在後台如何工作?
瀏覽器為了提高性能,向服務器請求資源時,都儘量多從本地緩存獲取,儘量少從服務器獲取。
具體行為我們可以通過指令來控制,通過設置 HTTP 響應頭來實現。
緩存處理相關的最常用指令包括:
- Cache-Control
- Expires
- Etag
- Last-Modified
如果沒有設置緩存控制指令,瀏覽器將從服務器獲取每個資源,這會增加頁面的加載時間。
沒有緩存設置的請求流程:
由瀏覽器決定如何在沒有服務器指示的情況下緩存信息。
不同瀏覽器策略不同,例如 Chrome 和 Safari 每次都從後端下載數據。
為了清楚地定義緩存的處理方式,讓我們深入瞭解一下緩存控制指令。
Etag(實體標籤)
Etag 可以讓我們在不用下載資源的情況下,就知道服務器上的資源是否變更了。
服務器在給瀏覽器發送資源文件時(例如 css 文件),會對此資源內容計算出一個 hash 值,作為此文件的 tag,一起發送給瀏覽器。
瀏覽器下次請求此資源文件時,先把這個 tag 發給服務器,HTTP header 信息例如:
If-None-Match: W/“1d2e7–1648e509289”
服務器和本地文件的 hash 值對比。
如果一樣,就告訴瀏覽器沒有變化,可以使用緩存文件,否則瀏覽器下載新文件。
使用Etag請求流-第一次加載:
使用Etag請求流-第二次加載:
啓用 Etag 緩存策略後,我們總是會去服務器檢查文件的哈希值,然後瀏覽器才會決定從緩存中提取文件或將其完全加載。
如果未修改,則無論您要請求的是10KB還是10MB的文件,只需80–100字節即可進行驗證。
Last Modified
服務器有每個文件的最後修改時間戳,在第一次文件加載之後,客户端會向服務器詢問此文件在某時間之後是否更改過。
HTTP header 信息例如:
If-Modified-Since: Fri, 13 Jul 2018 10:49:23 GMT
如果改了,就下載新文件,否則使用緩存。
看着挺好,但現實情況並不一定是這樣的,“Last-Modified” 是一個弱緩存頭信息,瀏覽器有自己的緩存策略,會自行決定是否從緩存中獲取資源或下載新文件,不同瀏覽器處理方式也不一樣。
使用 Last-Modified 的請求流程 - 第一次加載:
使用 Last-Modified 的請求流程 - 第二次加載(完美情況):
使用 Last-Modified 的請求流程 - 第二次加載(通常情況):
所以,“Last-Modified” 是不可靠的,我寧願完全不使用他。
Cache-Control max-age
這個指令告訴瀏覽器此文件在本地緩存多長時間。
以秒為單位,形式為:
Cache-Control: max-age=31536000
使用此策略後,瀏覽器完全不用向服務器發起請求了,直接使用本地緩存,非常快。
但是,沒有辦法確保這段時間內服務器中的文件不會修改。
因此,為了讓瀏覽器下載最新的文件,我們可以使用一些構建工具,例如 Webpack、Gulp。
每個文件都在服務器中進行預編譯,對文件內容進行 hash 計算,把 hash 值添加到文件名中,例如 “app-72420c47cc.css”。
這樣,文件內容的變化就可以反應在文件名上,對瀏覽器來講就是一個新的文件,舊文件的緩存也就沒有了,會從服務器上獲取新的。
這個方法適用於 CSS JS 和圖片文件。
no-cache
no-cache(無緩存)不意味着根本沒有緩存,它只是告訴瀏覽器在使用緩存之前先驗證服務器上的資源。
需要與 Etag 一起使用,因此瀏覽器將發送一個簡單請求並加載額外的80個字節以驗證文件的狀態。
對於 HTML 文件,就需要使用 “no-cache”。
最終方案
使用 Gulp,Webpack 這類工具將唯一的哈希值添加到 css,js 和圖像文件(如app-67ce7f3483.css)。
對於 js,css 和圖像文件,設置 Cache-Control:public,max-age = 31536000,不設置 Etag 和 Last-Modified。
對於 HTML 文件,設置 Cache-Control: no-cache 和 Etag。
翻譯整理自:
https://medium.com/pixelpoint...