👀 Nginx Http緩存的必要性!啟發式緩存有什么弊端?
- 簡介
- 啟發式緩存引發的問題
- nginx緩存配置
簡介
我們在使用React或者Vue開發項目中會使用hash、chunkhash、contenthash來給靜態資源文件進行命名。這帶來的好處便是當我們部署完項目后,用戶刷新頁面后會重新獲取html資源,html資源中的js或者css文件由于文件名發生變化會重新發起請求來獲取新的資源。當然我們有時候為了項目優化,我們還會對一些頁面模塊進行分包進行懶加載,有時候還會把一些模塊通過webpack魔法注釋chunkName
拆到一個包中。
http
緩存種類:我目前總結了三類,分別為強緩存、協商緩存、啟發式緩存
這篇文章介紹了強緩存和協商緩存 http緩存
那么如果響應頭中沒有配置強緩存和協商緩存,瀏覽器會觸發啟發式緩存。
啟發式緩存的緩存有效期計算公式為 (date - last-modified ) * 10%。取響應頭中 date 與 last-modified 值之差的百分之十作為緩存時間。啟發式緩存比較容易忽略,不了解啟發式緩存可能會因為這種默認的緩存方式而掉入坑里,但一旦你了解了瀏覽器啟發式緩存的機制,很多問題都可以得到解決。
啟發式緩存引發的問題
通常項目上線后會部署到Nginx服務器。假如我們并沒有配置任何響應頭來緩存靜態資源。那么是會帶來一些問題的。
前面已經說了在沒有配置任何http緩存的情況,瀏覽器會觸發啟發式緩存的。那么好,比如我們的項目經過第一次打包生成了幾個文件main-123abc.js、vender-345abc.js、main-789abc.css、chunk1-123abc.js、chunk1-123abc.css、chunk2-456abc.js、chunk2-456abc.css
。當用戶訪問頁面后,會觸發啟發式緩存的,而用戶并沒有關閉頁面。 這里的文件名hash我只是舉例。
第二天我們在項目里更新了某個chunk內的代碼,比如chunk1的代碼,那么經過構建工具打包又會重新生成一些文件。他們是main-123abc.js、vender-345abc.js、main-789abc.css、chunk1-321abc.js、chunk1-321abc.css、chunk2-456abc.js、chunk2-456abc.css
。文件名從 chunk1-123abc
變成了chunk1-321abc
,文件hash會變化,這一切都很正常。就這樣我們進行了第二次部署。
但此時問題來了(這個問題是建立在二次部署后,老頁面并沒有刷新),用戶訪問我們第一次部署的頁面并且有了啟發式緩存。但是這個緩存是有時效性的,他是會過期的,過期后瀏覽器會再次請求過期的那個文件。假如用戶訪問了chun1的頁面,但是我們已經進行了第二次部署,你覺得會找到chunk1-123abc.js和chunk1-123abc.css
嗎?肯定找不到的,那么用戶就會看到白屏或者樣式丟失。 當然用戶刷新頁面后就會正常。
此時http強緩存和協商緩存的就能解決這個問題。因為我們的靜態js、css文件經過了強緩存,用戶即便是不關閉頁面,訪問的依然是緩存。就不會出現白屏或者樣式丟失的問題。
nginx緩存配置
map $request_filename $cache_control {default "";~*\.(htm|html)$ "no-store";~*.* "max-age=31536000"; # 1年的秒數
}server {listen 80;server_name localhost;location / {alias /opt/dist/;try_files $uri /index.html;add_header Cache-Control $cache_control;}
}