網站緩存(網站的緩存控制策略最佳實踐及註意事項)

對於一個網站來講,性能關乎用戶體驗,你在更短的時間內打開網站,你將會留住更多的用戶。如果你的頁面十秒才能打開,那再好的用戶交互也是徒然。緩存控制是網站性能優化中至為常見及重要的一環,好的緩存控制,除瞭使網站在性能方面有所提升,在財務方面也有重要提升: 更好的緩存策略意味著更少的請求,更少的流量,更少的峰值帶寬,從而節省一大筆服務器或者 CDN 的費用。緩存控制策略就是 http caching 的策略,化繁為簡,最有效的策略往往是很簡單的。在最簡單的粗略下,你對 http cache 隻需要瞭解一個 Cache-Control 的頭部。一個較好的緩存策略隻需要兩部分,而它們隻需要通過 Cache-Control 控制:帶指紋資源: 永久緩存非帶指紋資源: 每次進行新鮮度校驗作圖如下:緩存控制策略帶指紋資源: 永久緩存Cache-Control: max-age=31536000天下武功,無堅不摧,唯快不破。資源請求最快的方式就是不向服務器發起請求,通過以上響應頭可以對資源設置永久緩存。靜態資源帶有 hash 值,即指紋對資源設置一年過期時間,即 31536000,一般認為是永久緩存在永久緩存期間瀏覽器不需要向服務器發送請求那為什麼帶有 hash 值的資源可以永久緩存呢?因為該文件的內容發生變化時,會生成一個帶有新的 hash 值的 URL。 前端將會發起一個新的 URL 的請求。非帶指紋資源: 每次進行新鮮度校驗Cache-Control: no-cache由於不帶有指紋,每次都需要校驗資源的新鮮度。(從緩存中取到資源,可能是過期資源)如果校驗為最新資源,則從瀏覽器的緩存中加載資源index.html 為不帶有指紋資源,如果把它置於緩存中,則如何保證服務器刷新數據時,被瀏覽器可以獲取到新鮮的資源?因此,使用 Cache-Control: no-cache 時,客戶端每次對服務器進行新鮮度校驗。PS:no-cache 與 no-store 的區別是什麼?即使每次校驗新鮮度,也不需要每次都從服務器下載資源: 如果瀏覽器/CDN上緩存經校驗沒有過期。這被稱為協商緩存,此時 http 狀態碼返回 304,指 Not Modified,即沒有變更。幸運的是,關於協商緩存,你無需管理,也無需配置, nginx 或者一些 OSS 都會自動配置協商緩存。而對於協商緩存,也有它們自己的算法,協商緩存的背後基於響應頭 Last-Modified/ETag。瀏覽器每次請求資源時,會攜帶上次服務器響應的 ETag/Last-Modified 作為標志,與服務端此時的 ETag/Last-Modified 作比較,來判斷內容更改。http 響應頭中的 ETag 值是如何生成的?而在操作系統底層,Last-Modified 往往通過文件系統(file system)中的 mtime 屬性生成。而 ETag 提供比 Last-Modified 更精細的檢驗粒度,由文件內容的 hash 或者 mtime/size生成。當然,這是後話。一定要為你的資源添加 Cache-Control 響應頭我會經常接觸到一些網站,他們的資源文件並沒有 Cache-Control 這個響應頭。究其原因,在於緩存策略配置這個工作的職責不清,有時候它需要協調前端和運維。那如果不添加 Cache-Control 這個響應頭會怎麼樣?是不是每次都會自動去服務器校驗新鮮度,很可惜,不是。此時會對資源進行強制緩存,而對不帶有指紋信息的資源很有可能獲取到過期資源。 如果過期資源存在於瀏覽器上,還可以通過強制刷新瀏覽器來獲取最新資源。但是如果過期資源存在於 CDN 的邊緣節點上,CDN 的刷新就會復雜很多,而且有可能需要多人協作解決。那默認的強制緩存時間是多少首先要明確兩個響應頭代表的含義:Date: 指源服務器響應報文生成的時間,差不多與發請求的時間等價Last-Modified: 指靜態資源上次修改的時間,取決於 mtimeLM factor 算法認為當請求服務器時,如果沒有設置 Cache-Control,如果距離上次的 Last-Modified 越遠,則生成的強制緩存時間越長。用公式表示如下,其中 factor 介於 0 與 1 之間:MaxAge = (Date – LastModified) * factorLM factorBundle Splitting:盡量減少資源變更得益於單頁應用與前端工程化的發展,經過打包後,基本上所有資源都是帶有指紋信息的,這意味著所有的資源都是能夠設置永久緩存。打包策略如下圖所示:緩存控制策略但僅僅如此瞭嗎?如果你所有的 js 資源都打包成一個文件,它確實有永久緩存的優勢。但是當有一行文件進行修改時,這一個大包的指紋信息發生改變,永久緩存失效。所以我們現在需要做到的是:當修改文件後,造成最小范圍的緩存失效。webpack 等打包工具雖然在 optimization 上內置瞭很多性能優化,但它不會幫你做這件事,這件事情需要自己動手。緩存控制策略此時我們可以對資源進行分層次緩存的打包方案,這是一個建議方案:webpack-runtime: 應用中的 webpack 的版本比較穩定,分離出來,保證長久的永久緩存react/react-dom: react 的版本更新頻次也較低vendor: 常用的第三方模塊打包在一起,如 lodash,classnames 基本上每個頁面都會引用到,但是它們的更新頻率會更高一些。另外對低頻次使用的第三方模塊不要打進來pageA: A 頁面,當 A 頁面的組件發生變更後,它的緩存將會失效pageB: B 頁面echarts: 不常用且過大的第三方模塊單獨打包mathjax: 不常用且過大的第三方模塊單獨打包jspdf: 不常用且過大的第三方模塊單獨打包隨著 http2 的發展,特別是多路復用,初始頁面的靜態資源不受資源數量的影響。因此為瞭更好的緩存效果以及按需加載,也有很多方案建議把所有的第三方模塊進行單模塊打包。小結原地址:https://mp.weixin.qq.com/s/AJqUxIHhZBzhDGh2w9A2Kg

本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://kuaisubeian.cc/48283.html

kuaisubeian