最近在寫一個web容器,容器有一一個小功能是要對web做緩存,所以最近一直研究ios的web緩存,在研究過程中遇到不少問題也收貨頗多,現總結如下:
web緩存的目的:節省服務器資源;使頁面加載更流暢,減少等待時間增加用戶體驗;節省用戶流量等。。。
web緩存有很多種方法NSURLCache、App Cache(Manifest文件)、NSURLProtocol:
1、NSURLCache(ios系統自帶的,並不知是web緩存纔會有):
(1)NSURLCache-http響應:
在我們發request請求時,ios系統會默認參與緩存,使用的是默認的NSURLCache類,可以通過NSURLCache的sharedURLCache方法獲取。request在初始化的時候可以選擇cachePolicy值(緩存策略)
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
NSURLRequestUseProtocolCachePolicy = 0,
NSURLRequestReloadIgnoringLocalCacheData = 1,// 從不讀取緩存,但請求後將response緩存起來
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2,// (可能讀取的是過期數據)緩存中沒有才去發起請求加載,有就不進行網絡請求了
NSURLRequestReturnCacheDataDontLoad = 3,// (可能讀取的是過期數據)緩存中沒有不加載,絕不發起網絡請求,緩存中沒有則返回錯誤
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
request默認使用NSURLRequestUseProtocolCachePolicy=0;即根據http響應數據進行緩存,這就需要研究下response的幾個字段了:
在根據響應返回的字段又分爲強制緩存和對比緩存:https://blog.csdn.net/sinat_20894673/article/details/89061172
1.1.強制緩存:對於第一次請求資源,在沒有資源緩存的情況下,會發送資源請求請求服務器獲取對應的資源。在http響應頭會有強制緩存的標誌(Expires/Cache-Control)。分別對應http1.0和http1.1的緩存規則。當下次請求對應資源的時候,根據強制緩存的標誌,如果還在緩存期內,那麼直接使用本地緩存,不在發送網絡請求。
1.1.1》Expires:在http1.0中,代表資源過期時間。使用絕對時間來標記資源的過期時間,但是由於服務器與客戶端之間可能存在差異,會導致緩存的不準確。eg:Expires:Sat,06 Apr 2019 14:11:37 GMT
1.1.2》Cache-Control:http1.1,一般取值private、public、no-cahe(使用對比緩存來驗證緩存數據)、max-age=300s(300s有效期)、no-store(不使用緩存,一般來說都會設置緩存);默認private
1.2.對比緩存:在沒有設置強制緩存的情況下,就會比較對比緩存。在使用對比緩存的時候,會將之前在客戶端的對比緩存的標誌發送到服務器,與服務器上的版本進行比較,如果資源沒有被修改過,那麼直接返回304,此時使用本地緩存的資源,若資源已過期,則返回新的資源,此時的狀態碼是200。
1.2.1》Last-Modified:在響應請求時,告訴瀏覽器的最後修改時間,http1.0。但是由於該標誌是根據文件的修改時間決定的,而且是基於秒級,如果在一秒內對文件修改兩次的話,此時last-modified的值是一致的。
1.2.1》Etag:是資源的唯一標誌,在資源沒有發生變化的時候,Etag值不變,這個標記同樣會通過響應頭返回給客戶端。該標誌就是爲了彌補last-modified的不足。http1.1
Etag 主要爲了解決 Last-Modified 無法解決的一些問題:
1、一些文件也許會週期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認爲這個文件被修改了,而重新GET;
2、某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
3、某些服務器不能精確的得到文件的最後修改時間。
總結
對於靜態資源的緩存一般都會設置強制緩存和對比緩存,當強制緩存與對比緩存同時存在的時候,優先使用強制緩存,在強制緩存中,cache-control的優先級大於expires。當強制緩存存在的時候,瀏覽器直接使用本地緩存,並且請求返回200,此時的請求是不會請求服務器的。而當強制緩存過期的時候,則會使用對比緩存,此時會發送一個請求到服務器,如果此時文件還未被更新,則請求返回304,並且會使用本地的緩存文件。否則服務器返回200,並且返回對應的新的資源。
(2)NSURLCache-存儲位置:
1》UIWebView(用UIWebView加載百度首頁爲例)https://blog.csdn.net/fishmai/article/details/60127023
用一段示例代碼說明:/Users/yangyangzi/Desktop/testUiweb/uiweb/dd.TestUIWeb\ 2019-09-07\ 19\:58.49.523.xcappdata/AppData/Library/Caches/dd.TestUIWeb (注:dd.TestUIWeb爲bundleid)
在沙盒的caches目錄下:
NSURLCache-內容詳解:
主要內容都在Cache.db數據庫中,下面來看下此數據庫中三個關鍵的表:
cfurl_cache_response 中根據request_key查到entry_ID
cfurl_cache_blob_data中根據entry_ID找到response_object
cfurl_cache_receiver_data中根據entry_ID找到receiver_data
根據receiver_data又能找到與Cache.db同級的文件夾fsCachedData中的對應文件,例如上邊(四張圖中選中的行的entry_ID=5的圖片即爲plus_log_web.png 百度logo)
2》WKWebView(用WKWebView加載百度首頁爲例)https://www.cnblogs.com/lolDragon/p/6861370.html
解開wk的包查看沙盒目錄如下:
查看cache.db詳情如下:
的確你沒看錯,wk的cache.db庫裏的三個關鍵表格是空的,而且不像UIweb,wk的沙盒目錄裏沒有fsCachedData文件夾,但是wk的沙盒中多了兩個Webkit文件夾,其中一個在Caches文件夾下,另一個與Caches文件夾同層。先來看下這個Caches文件夾下的Webkit文件夾:
WebKit文件夾裏面存儲的就是WKWebVieW下面的緩存文件了(包含了JS/CSS/圖片等);
分析:wkweb的Cache.db文件是空的,說明在推出wkwebview後,ios系統將web的緩存和NSURLCahe分開了,(用AFN發請求發現,Cache.db中有url存儲,說明Cache.db只存儲除wkweb發送的請求,而wkweb的網絡緩存都放在了webkit文件夾下)
與Caches文件夾同層的webkit文件夾,應該是wkwebview的磁盤存儲了。
2、App Cache(Manifest文件):這裏就需要web端的同學去操作了:Manifest文件是web端同學在html中的一個manifest
創建 .manifest的文件:https://www.cnblogs.com/lolDragon/p/6861370.html
manifest文件首先必須已 CACHE MANIFEST開頭, 然後包含了三個部分CACHE: NETWORK: FALLBACK:三個部分,其中CACHE下邊寫的是要緩存的文件。
application cache緩存的位置:
不推薦
3、使用NSURLProtocol緩存web文件:
這種方法也是我最近在扣的,很多坑裏邊,考慮到篇幅問題,再新寫一篇
NSURLCache緩存的位置:https://www.jianshu.com/p/e84f2e897e18;
ios html5使用緩存並及時更新方案總結:https://www.cnblogs.com/lolDragon/p/6861370.html
清除緩存:https://www.cnblogs.com/lolDragon/p/6774509.html
https://www.itcodemonkey.com/article/14997.html
webkit的緩存機制:https://blog.csdn.net/yl02520/article/details/22300467
你可能並不需要攔截webview的靜態資源:https://www.jianshu.com/p/40d9f599f869
http請求中靜態資源的緩存:https://blog.csdn.net/sinat_20894673/article/details/89061172
NSURLCache:https://nshipster.cn/nsurlcache/
ios wkwebview(NSURLProtol)攔截js、css、圖片資源:https://www.jianshu.com/p/4fc13d4d5607
NSURLCache使用UIWebViewURL攔截:https://www.jianshu.com/p/3fdfef453513