如何解決靜態資源的快取問題
最近寫了一個面向大眾的導航站,初期一直在修改js和css,由於是託管到coding上的,瀏覽器的快取問題是真的要命,自己倒是知道清理快取,但其他人不知道啊,所以在網上查了下解決辦法,特來總結一下
前言
瀏覽器的快取機制其實是一個很好的最佳化機制,可以避免重複請求相同的資源,減輕伺服器的壓力,也可以加快使用者的二次讀取。但凡事都有優缺點,快取的存在會導致css,js或者其他靜態資源不能及時更新。有時修改了html,html一般不會讀取快取,但css和js讀取了快取,就會出現一些莫名其妙的問題,而到了使用者那邊,則會一臉懵逼。
瀏覽器的快取原理
這個我也不太懂,就知道分為強制快取和協商快取。當二次開啟網頁時,瀏覽器會先對快取發起http請求,只要請求的資源存在快取並且該資源的請求頭
expires
和
cache-control
中存在快取的標誌,那就預設讀取快取,如果快取失效但快取依然存在,這時有會對伺服器發出http請求,透過
last-modified
和
etag
兩個請求頭驗證是否存在協商快取,存在協商快取就讓瀏覽器照樣讀取快取。
當然,如果你資源已經不存在了或者明確禁止快取,那瀏覽器也不可能使用快取,這也是解決快取問題的辦法
強制快取
強制快取兩個請求頭,
expires
和
cache-control
expires
不怎麼用,是http1。0提出的一個表示資源過期時間的header 而
cache-control
出現於 HTTP / 1。1,優先順序高於 Expires,同樣也可以表示資源過期時間 當然
cache-control
並沒有這麼簡單,有很多值,但常用的基本就是下面5個值 - public:所有內容都將被快取(客戶端和
代理伺服器
都可快取) - private:所有內容只有客戶端可以快取,Cache-Control的預設取值 - no-cache:客戶端快取內容,但是是否使用快取則需要經過協商快取來驗證決定 - no-store:所有內容都不會被快取,即不使用強制快取,也不使用協商快取 - max-age=xxx (xxx is numeric):快取內容將在xxx秒後失效
強制快取是否生效,可以檢視控制檯的network選項,下面的size屬性,一般就是
from memory cache
或者
from disk cache
,一個是從記憶體中載入快取,一個是硬碟中載入快取,區別就是記憶體要快些,一般先是讀取硬碟中的快取,要是你重新整理一下,就從記憶體中讀取,不然重新整理的時候怎麼那麼快
協商快取
當強制快取失敗,瀏覽器就請求伺服器,如果伺服器覺得用快取沒問題,資源又沒有更新,那麼,即使快取設了到期時間,瀏覽器依然會讀取,此時伺服器返回304,如果資源更新了,就從伺服器請求更新,返回200。如何判斷資源是否更新,就是靠
last-modified
和
etag
兩個請求頭,這裡我就不多講了
但是要注意,強制快取要優先於協商快取,所以嘛,就算你更新了,瀏覽器依舊會讀取快取
,這也就是問題的由來,解決辦法很簡單,要麼直接禁用快取,告訴瀏覽器不準使用我的快取,每次都從伺服器載入。要麼就是把檔名字改了,快取名字對不上也就不會讀取快取了
解決辦法
知乎上有個回答說的挺好
瀏覽器是好人(meta),瀏覽器有點壞(版本號),瀏覽器老子看你不爽了,我要“欺騙你”(md5)
meta快取頭設定為禁止快取
在html的head標籤中加入下面內容,就可以禁止瀏覽器讀取快取
<
meta
http-equiv
=
“Cache-Control”
content
=
“no-cache, no-store, must-revalidate”
/>
<
meta
http-equiv
=
“Pragma”
content
=
“no-cache”
/>
<
meta
http-equiv
=
“Expires”
content
=
“0”
/>
Cache-Control
作用於
HTTP1。1
Pragma
作用於
HTTP1。0
Expires
作用於
proxies
但這樣瀏覽器在資源沒修改的時候也不能載入快取,十分影響體驗
js、css加上版本號
當請求js、css的時候,給他們最後加上版本號,瀏覽器發現版本高了,就自然而然不會讀取低版本的快取了 版本號並不需要改變檔名,只需要在呼叫js、css的時候在最末尾加上
?v=1。0
即可,比如
custom。css
?v=1。0
main。js?v=2。0
當然版本號也可以自動新增
隨機數
,不過這樣就違背了版本號的初衷了,這樣同樣瀏覽器在資源沒修改的時候也不能載入快取,影響體驗 隨機版本號的新增方法,使用一個隨機函式即可,當然,這樣就只能透過js中寫js的呼叫語句,比如
document
。
write
(
“