一:現象
- 客戶端加載過H5頁面A,后來H5修改為A'發布之后,在很長一段時間內,客戶端一直展示的是A,沒有更新為A'。
- 重啟之后依然沒有更新,只有清除緩存或者重裝APP才會更新。
二:分析
根據現象得出,是由於webview的緩存導致頁面一直沒有更新。但是為什么沒有更新?更新的機制是什么?應該怎么修改?
首先看下客戶端的緩存機制,CacheMode一共有五種
CacheMode { // 如果頁面沒有強制任何特定行為(依賴服務端控制),如果本地有未過期的緩存,就會直接加載本地緩存,否則就請求網絡 LOAD_DEFAULT = -1 // 從API 11開始就廢棄了,和LOAD_DEFAULT行為一致 LOAD_NORMAL = 0 // 只要本地有緩存,不管有沒有過期,都使用本地緩存。否則就請求網絡 LOAD_CACHE_ELSE_NETWORK = 1 // 忽略本地緩存(就算有也不用),直接請求網絡 LOAD_NO_CACHE = 2 // 只使用本地緩存,不請求網絡 LOAD_CACHE_ONLY = 3 }
重點看下LOAD_DEFAULT模式,這個是依賴服務端配置的緩存策略
http協議緩存機制
http協議緩存機制是指通過 HTTP 協議頭里的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等字段來控制文件緩存的機制。
Expires 是 HTTP1.0 標准中的字段,Cache-Control 是 HTTP1.1 標准中新加的字段,功能一樣,都是控制緩存的有效時間。當這兩個字段同時出現時,Cache-Control 是高優化級的。
Cache-Control參數可參考 淺談http中的Cache-Control
三:解決方案
客戶端:CacheMode使用LOAD_DEFAULT即可,依賴服務端控制緩存策略。為了解決線上版本緩存有效期時間過長的問題,可以在請求的url后面加無效參數,例如#,欺騙瀏覽器url變動,強制瀏覽器去服務器更新一次。
服務端:修改nodejs express服務,設置靜態資源的時候設置了下這個Cache-Control屬性。修改方式可參考 Express 中設置緩存Cache-control的maxAge
服務器配置:Nginx服務器配置Cache-Control也是可行的。
緩存策略需要根據具體業務來確定,如果該頁面沒有要求實時更新,可以使用max-age=XX來控制,在再XX秒時間范圍內使用緩存,否則就請求網絡。
四:測試流程
使用max-age=60驗證頁面更新情況
- 前提,清除緩存,服務端先加上max-age屬性
- 客戶端先進入頁面緩存一次。
- h5修改資源發布
- 客戶端再60秒之內打開頁面,沒有更新,60秒之后再次打開,頁面正常更新。
五:注意事項
- 如果之前服務端沒有加任何控制緩存的參數(Cache-Control),客戶端緩存了該H5頁面,此時修改服務端緩存策略,客戶端在緩存過期之前是不會重新請求資源的。必須等到客戶端緩存過期,或者清除緩存才可以。
- HTML頭部添加
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
並沒有生效,被忽略了
- 在服務端沒有配置任何緩存策略時,Android緩存有效期時間會很長,也就是長時間不會更新。而iOS每次進入頁面都會更新,由於iOS和Android內核不一樣,iOS是Safari,Android是chromium,處理方式可能會有差異。
- 在服務端沒有加任何控制緩存的參數情況下,使用pc端瀏覽器打開H5,在H5修改之后,谷歌瀏覽器也是沒有立即更新的,必須使用強制刷新(Shift+F5),但是火狐瀏覽器F5就可以正常刷新了。谷歌瀏覽器和Android內置瀏覽器都是chromium內核,表現基本一致。
- 查看網頁響應頭
瀏覽器打開該網頁,按F12,選擇Network,然后再刷新下網頁,選擇左下欄第一個.html的頁面,右面的Headers里面可以看到Cache-Control,說明服務端配置生效了。
參考:
