手摸手教你解決重定向快取問題

唱跳rap和web發表於2020-01-09

手摸手教你解決重定向快取問題

手摸手教你解決重定向快取問題

問題產生:

測試粑粑:測試環境已經搭好了,前端打個包吧!
weber:好嘞!快速輸入命令:npm run build:stagging
三分鐘後……
測試粑粑:是不是打錯包了?怎麼還沒變?
weber:重新整理下頁面試試!
測試粑粑:沒用鴨~
weber:蛤~清理下瀏覽器快取!
測試粑粑:出來了,**牛皮鴨!!!

問題到這裡,我陷入了沉思,咋回事呢,如果每次釋出需要使用者手動清除瀏覽器快取,這無疑是一個巨大的bug?於是開始列出了問題排查清單:
1、重新整理頁面重新進行了doc【index.html】請求,無效;而清理瀏覽器快取缺生效了,說明瀏覽器快取了檔案導致重新整理請求時還是之前的檔案。
2、webpack打包時,outputjscss加上了hash,那jscss應該就不會快取。

開始排查

一、檢查了webpack打包配置:

module.exports = {
  context : path.join(__dirname,'src'),
  entry:{
    main: './index.js',
    vender:['./jquery.js','./test.js']
  },
  module:{
    rules:[{
      test:/\.css$/,
      use: extractTextPlugin.extract({
        fallback:'style-loader',
        use:'css-loader'
      })
    }]
  },
  output:{
    path:path.join(__dirname, '/dist/js'),
    filename: 'bundle.[name].[hash].js',
  },
  plugins:[
    new extractTextPlugin('../css/bundle.[name].[hash].css')
  ]
}
複製程式碼

發現webpack打包沒有問題。

手摸手教你解決重定向快取問題
二、打包後的檔案也沒有問題。

手摸手教你解決重定向快取問題
三、打包後生成的index.html檔案引入。

手摸手教你解決重定向快取問題
三、檢視network請求才恍然大悟:

index.html304請求,那說明index.html被快取了。

解決問題

開始尋找解決辦法,方法有很多,有前端配置的,也有後端配置的。

考慮到webpack打包生成的html只是作為引入jscss的容器,若只是不快取html檔案,代價其實很小。選擇如下方法:

1、在html head頭部新增不快取html配置:

注:metatml語言head區的一個輔助性標籤,其中的http-equiv欄位定義了伺服器和使用者代理的一些行為。在之前的規範中,metahttp-equiv欄位中有以下值與http header快取相關的欄位功能類似

<head>
  <meta http-equiv="pragma" content="no-cache">
  <meta http-equiv="cache-control" content="no-cache">
  <meta http-equiv="expires" content="0">
</head>
複製程式碼

若採用這種方式,請在public檔案加下的index.html配置。

2、修改nginx.conf,增加add_header Cache-Control 'no-cache, no-store, must-revalidate'不快取html配置:

server {
  listen       80;
  server_name  localhost;

  root        /usr/share/nginx/html;
  index       index.html;

  location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
      expires 1M;
      add_header Cache-Control "public";
  }

  location / {
      add_header Cache-Control 'no-cache, no-store, must-revalidate';
  }

  error_page  404              /index.html;
}
複製程式碼

其實這兩個配置都是在請求head加上不快取html的配置,一個在前端,一個在運維。翻閱w3c文件發現,但現在w3c的規範欄位中這些值已經被移除,一個很好的理由是:

Putting caching instructions into meta tags is not a good idea, because although browsers may read them, proxies won't. For that reason, they are invalid and you should send caching instructions as real HTTP headers.

綜合之後還是第二種方案較為完善。

bug再現:

weber:這次修改了nginx配置,這次打包應該不會出現上次的快取問題了,不用手動清楚瀏覽器快取了!
測試粑粑:牛皮鴨,我試試~
weber:(自信的小表情,期待的小紅手)~
測試粑粑:還是有問題鴨!還是沒更新過來!
weber:你是直接請求是吧?有沒有重新整理頁面?
測試粑粑:沒有,直接請求的~
weber:好了,我知道了!

問題到這裡,又出現了bug。如果直接請求網址,是會請求到最新的html檔案,但是還會存在使用者不重新整理直接請求的情況。

理清思路:

其實到這一步問題已經很清晰了,重新理一遍webpack打包過程、瀏覽器快取策略,問題就很容易解決了。
一、webpack打包:

public/index.html:檔案是一個會被 html-webpack-plugin 處理的模板。在構建過程中,資源連結會被自動注入。另外,Vue CLI 也會自動注入 resource hint (preload/prefetch、manifest 和圖示連結 (當用到 PWA 外掛時) 以及構建過程中處理的 JavaScriptCSS 檔案的資源連結。ouput裡面的檔案都會inject

二、HTTP重定向:

伺服器的nginx配置如下:

手摸手教你解決重定向快取問題

假若輸入:https://example.comhttps://example.com/a都會定位到root下的index.html檔案,也會觸發請求html檔案。

三、瀏覽器快取:

手摸手教你解決重定向快取問題

再次檢視增加了不快取html檔案,請求狀態變成了200

手摸手教你解決重定向快取問題

因此,在不重新整理瀏覽器的情況下請求,html是沒有被請求的,仍然是第一次輸入網址請求回來的html檔案,裡面的jscss也是之前的,所以瀏覽器不會再去請求jscss檔案。解決辦法:

axios請求加上版本號,如果版本號對應不上,則返回code,讓前端去與使用者互動是否已經更新了,需要重新整理頁面。

相關文章