強快取和協商快取
在介紹快取的時候,我們習慣將快取分為強快取和協商快取兩種。兩者的主要區別是使用本地快取的時候,是否需要向伺服器驗證本地快取是否依舊有效。顧名思義,協商快取,就是需要和伺服器進行協商,最終確定是否使用本地快取。
兩種快取方案的問題點
強快取我們知道,強快取主要是通過http請求頭中的cache-control和expire兩個字段控制。expire是http1.0標準下的字段,在這裡我們可以忽略。我們重點來討論的cache-control這個字段。
一般,我們會設定cache-control的值為「public, max-age=***」,表示在***秒內再次訪問該資源,均使用本地的快取,不再向伺服器發起請求。
顯而易見,如果在***秒內,伺服器上面的資源更新了,客戶端在沒有強制重新整理的情況下,看到的內容還是舊的。如果說你不著急,可以接受這樣的,那是不是完美?然而,很多時候不是你想的那麼簡單的,如果發布新版本的時候,後台介面也同步更新了,那就gg了。有快取的使用者還在使用舊介面,而那個介面已經被後台乾掉了。怎麼辦?
協商快取
協商快取最大的問題就是每次都要向伺服器驗證一下快取的有效性,似乎看起來很省事,不管那麼多,你都要問一下我是否有效。但是,對於乙個有追求的碼農,這是不能接受的。每次都去請求伺服器,那要快取還有什麼意義。
最佳實踐
快取的意義就在於減少請求,更多地使用本地的資源,給使用者更好的體驗的同時,也減輕伺服器壓力。所以,最佳實踐,就應該是盡可能命中強快取,同時,能在更新版本的時候讓客戶端的快取失效。
在更新版本之後,如何讓使用者第一時間使用最新的資源檔案呢?機智的前端們想出了乙個方法,在更新版本的時候,順便把靜態資源的路徑改了,這樣,就相當於第一次訪問這些資源,就不會存在快取的問題了。
偉大的webpack可以讓我們在打包的時候,在檔案的命名上帶上hash值。
entry:,
output:
複製**綜上所述,我們可以得出乙個較為合理的快取方案:
html:使用協商快取。
css&js&:使用強快取,檔案命名帶上hash值。
雜湊也有講究
webpack給我們提供了三種雜湊值計算方式,分別是hash、chunkhash和contenthash。那麼這三者有什麼區別呢?
hash:跟整個專案的構建相關,構建生成的檔案hash值都是一樣的,只要專案裡有檔案更改,整個專案構建的hash值都會更改。
chunkhash:根據不同的入口檔案(entry)進行依賴檔案解析、構建對應的chunk,生成對應的hash值。
contenthash:由檔案內容產生的hash值,內容不同產生的contenthash值也不一樣。
顯然,我們是不會使用第一種的。改了乙個檔案,打包之後,其他檔案的hash都變了,快取自然都失效了。這不是我們想要的。
那chunkhash和contenthash的主要應用場景是什麼呢?在實際在專案中,我們一般會把專案中的css都抽離出對應的css檔案來加以引用。如果我們使用chunkhash,當我們改了css**之後,會發現css檔案hash值改變的同時,js檔案的hash值也會改變。這時候,contenthash就派上用場了。
etag計算
nginx
nginx官方預設的etag計算方式是為"檔案最後修改時間16進製制-檔案長度16進製制"。例:etag: 「59e72c84-2404」
express
express框架使用了serve-static中介軟體來配置快取方案,其中,使用了乙個叫etag的npm包來實現etag計算。從其原始碼可以看出,有兩種計算方式:
方式一:使用檔案大小和修改時間
function stattag (stat)
複製**
方式二:使用檔案內容的hash值和內容長度
function entitytag (entity)
// compute hash of entity
var hash = crypto
.createhash('sha1')
.update(entity, 'utf8')
.digest('base64')
.substring(0, 27)
// compute length of entity
var len = typeof entity === 'string'
? buffer.bytelength(entity, 'utf8')
: entity.length
return '"' + len.tostring(16) + '-' + hash + '"'
}複製**etag與last-modified誰優先
協商快取,有etag和last-modified兩個字段。那當這兩個字段同時存在的時候,會優先以哪個為準呢?
在express中,使用了fresh這個包來判斷是否是最新的資源。主要原始碼如下:
function fresh (reqheaders, resheaders)
// always return stale when cache-control: no-cache
// to support end-to-end reload requests
// var cachecontrol = reqheaders['cache-control']
if (cachecontrol && cache_control_no_cache_regexp.test(cachecontrol))
// if-none-match
if (nonematch && nonematch !== '*')
var etagstale = true
var matches = parsetokenlist(nonematch)
for (var i = 0; i < matches.length; i++)
}if (etagstale)
}// if-modified-since
if (modifiedsince)
}
快取 瀏覽器快取
瀏覽器快取 brower caching 是瀏覽器在本地磁碟對使用者最近請求過的文件進行儲存,當訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁碟載入文件 1 瀏覽器第一次請求時,會發出一組 http 頭,用來指導瀏覽器如何進行快取。伺服器規定乙個資源是否要進行快取,主要由響應頭中的expires...
瀏覽器快取
1.為什麼使用瀏覽器快取 以前了解的動態指令碼加速,或者動態內容快取之類,他們的原理都是避免伺服器重複計算,結果仍保留在伺服器端,這樣獲取資料還得從伺服器檢索然後傳送到使用者瀏覽器,如果我們把這些結果放在瀏覽器中,就省去了伺服器的查詢和網路傳輸,瀏覽器快取很好的實現了這個功能 2.瀏覽器快取存放在哪...
瀏覽器快取
瀏覽器快取知識歸納 瀏覽器快取是提公升網頁效能的一大利器,但是,也是一把雙刃劍。利用的好網頁的效能會有大幅度提公升,伺服器的壓力也會減小。利用的不好,也會遇到很多的問題。本文結合瀏覽器快取的知識,結合真實案例進行分析,希望對讀者有所幫助。瀏覽器快取分類 瀏覽器快取分為強快取和協商快取,瀏覽器載入乙個...