vue SPA項目,瀏覽器和nginx反向代理緩存問題解決實方案

  1. 問題背景
    a.瀏覽器端在每次發佈新的版本時候,總會出現由於單頁面項目中index.html文件(200 ok from disk cache 不發送請求,直接取用了本地磁盤緩存)和服務端版本不一致的問題,致使用戶不能及時更新,須要經過手動刷新來強制從服務端更新文件。


    b.補充一下,服務端和瀏覽器之間架構。

  2. 三級緩存問題
    上述,咱們看到瀏覽器沒有發出請求直接從磁盤中取出index.html文件,這實際上是二級緩存。 
    當瀏覽器訪問的服務器沒有設置緩存時,瀏覽器先200 OK from memory cache,若是瀏覽器緩存中沒有該文件,那麼瀏覽器會200 OK from disk cache 從磁盤中找改文件,若是還找不到,瀏覽器會從服務端請求該文件下載使用。css

  3. Last-Modified/If-Modified-Since
    a.當瀏覽器第一次請求一個url時,服務器端的返回狀態碼爲200,同時HTTP響應頭會有一個Last-Modified標記着文件在服務器端最後被修改的時間。

    b.瀏覽器第二次請求上次請求過的url時,瀏覽器會在HTTP請求頭添加一個If-Modified-Since的標記,用來詢問服務器該時間以後文件是否被修改過。html

  4. Etag/If-None-Match
    a.當瀏覽器第一次請求一個url時,服務器端的返回狀態碼爲200,同時HTTP響應頭會有一個Etag,存放着服務器端生成的一個序列值。

    b.瀏覽器第二次請求上一次請求過的url時,當瀏覽器第一次請求一個url時,服務器端的返回狀態碼爲200,同時HTTP響應頭會有一個Last-Modified標記着文件在服務器端最後被修改的時間。

  5. Etag 主要爲了解決 Last-Modified 沒法解決的一些問題:

    a.Etag和Last-Modified特色:

    1).它們都屬於協商緩存,對內容的有效性進行驗證。
    2).Etag的值一般爲文件內容的哈希值;而Last-Modified爲最後修改的時間。
    3).Last-Modified只能精確到秒,秒以內的內容更新Etag才能檢測。
    4).文件有時會定時從新生成相同內容,Last-Modified不能很好辨別,某些服務器甚至不能精確的獲得文件的最後修改時間。
    5).Etag每次服務端生成都須要進行讀寫操做,而Last-Modified只須要讀取操做,Etag的消耗是更大的。

    Etag更像是Last-Modified的一種補充、完善。

  6. Expires
    Expires是RFC 2616(HTTP/1.0)協議中和網頁緩存相關字段。用來控制緩存的失效日期,要注意的是,HTTP/1.0有一個功能比較弱的緩存控制機制:Pragma,使用HTTP/1.0的緩存將忽略Expires和Cache-Control頭。
    能夠在nginx中設置 expires:-1; 以下

    其它配置:
    location ~ \.(wma|wmv|asf|mp3|mmf|zip|rar|swf|flv)$ {
                   root /var/www/upload/;
                   expires max;
           }複製代碼

    expires 指令能夠控制 HTTP 應答中的「 Expires 」和「 Cache-Control 」的頭標(起到控制頁面緩存的做用)
    語法:expires [time|epoch|max|pff]
    默認值:off
    expires指令控制HTTP應答中的「Expires」和「Cache-Control」Header頭部信息,啓動控制頁面緩存的做用
    time:可使用正數或負數。「Expires」頭標的值將經過當前系統時間加上設定time值來設定。
    time值還控制"Cache-Control"的值:
    負數表示no-cache
    正數或零表示max-age=time
    
    epoch:指定「Expires」的值爲 1 January,1970,00:00:01 GMT
    max:指定「Expires」的值爲31 December2037 23:59:59GMT,"Cache-Control"的值爲10年。
    -1:指定「Expires」的值爲當前服務器時間-1s,即永遠過時。
    off:不修改「Expires」和"Cache-Control"的值
    
    expires使用了特定的時間,而且要求服務器和客戶端的是中嚴格同步。
    而Cache-Control是用max-age指令指定組件被緩存多久。
    對於不支持http1.1的瀏覽器,仍是須要expires來控制。因此最好能指定兩個響應頭。
    但HTTP規範規定max-age指令將重寫expires頭。複製代碼
  7. 在設置Expires、Etag/If-None-Match、Last-Modified/If-Modified-Since緩存機制下,瀏覽器第一次請求和第二次請求緩存機制
    a.第一次請求

    b.第二次請求
    vue

  8. 用戶操做與緩存
  9. 基於vue-cli3.x腳手架下打包的spa項目緩存機制方案
    a.思路
    spa項目的網站域名映射的ip地址下入口文件是index.html,除此以外,js、css、img、font等等靜態文件都是從index.html下加載出來的。
    在vue-cli3.x腳手架打包下的js、css、img、font等靜態文件名都是包含hash,因此每次打包index.html加載出來的文件都不會出現相同名稱文件,所以也不會出現緩存問題。
    所以,咱們只須要經過配置nginx,設置協商緩存機制,每次發版本後,讓瀏覽器每次使用的index.html,這樣js、css、img、font等靜態文件都是最新。
    本質上,我只須要設置index.html受nginx配置的緩存機制的影響就行了,js、css、img、font等靜態文件能夠留給瀏覽器自身的緩存機制來控制,當不是第一次請求js、css、img、font等靜態文件時,這些資源文件能夠from disk cache/from memory cache ,直接從緩存中取對應的文件,這樣大大減小服務器的資源消耗,同時,經過網友文件的加載速度和頁面渲染速度。

    b.遇到的問題
    在nginx配置過程,咱們嘗試取捕捉index.html文件,捕捉到以後設置以下:

    location ^~ /aa/ {  
            proxy_set_header  X-Real-IP  $remote_addr;
            #html 文件不緩存(你也能夠設置爲協商緩存,可是參考其餘大廠方案,通常index.html入口文件都不做緩存,一方面是由於index.html很小基本在1KB左右,另外這個文件內容變化頻繁)
            if ($request_filename ~* ^.*?.(html|htm)$){
                expires -1s;
                add_header Cache-Control no-cache;
               }
             proxy_pass  http://XXX/aa/;               
          } 複製代碼

    可是這樣是捕捉不到index.html的,沒法控制index.html的緩存。
    緣由分析,是由於咱們在捕捉過程沒有一個文件路徑是含有.html後綴名的,所以沒法過濾出index.html加以設置。

    c.解決方案
    咱們沒法經過捕捉含有.html後面的路徑,可是咱們知道「/aa/」所對應的文件就是index.html,因此咱們來捕捉這個「/aa/」路徑,且不捕捉該路徑下子級文件(這樣把子文件夾中的js、css、img、font等靜態文件也設置來),配置以下:

    location ^~ /aa/ {  
       proxy_set_header  X-Real-IP  $remote_addr;        #html 文件不緩存(你也能夠設置爲協商緩存,可是參考其餘大廠方案,通常index.html入口文件都不做緩存,一方面是由於index.html很小基本在1KB左右,另外這個文件內容變化頻繁)
            if ( $request_uri = "/aa/") {
                expires -1s;
                add_header Cache-Control no-cache;
           #add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate"; }
             proxy_pass  http://XXX/aa/;           
          } 複製代碼
    如此,咱們就能簡單的過濾出index.html,並加以設置緩存。
    設置完成後瀏覽器第一次加載:


    設置完成後瀏覽器第二次加載:


    經過以上設置,咱們能夠很輕鬆的解決了瀏覽器和服務器之間的緩存問題。

    有建議或問題能夠加羣qq交流535798405
相關文章
相關標籤/搜索