微信瀏覽器內單頁應用緩存問題解決方案實踐(轉,實踐有效以此記錄)

原文鏈接:https://blog.csdn.net/slw632915651/article/details/89520845

一、問題背景

問題描述:

微信內單頁web應用,在進行版本迭代的時候,嚐嚐會遇到一個老大難問題。----緩存

大部分用戶,通過鏈接進入我們的應用,一般都不會去手動刷新一下我們的應用(右上角三個點,然後點擊刷新),

這樣就會導致我們對程序版本迭代和內容更新的時候,總有一些手機用戶因爲緩存原因,內容無法及時的更新或者產生錯誤的展示。

系統環境:

前端單頁頁面(vue頁面通過vue-cli打包生成的單頁)+ Nginx反向代理服務(充當靜態資源服務器) + 微信瀏覽器
二、問題分析

首先得吐槽一下微信端的瀏覽器內核,簡單的用一個段子來形容它:微信瀏覽器就是IE和陽光沙灘(sun of beach)的私生子。

我們通常用來處理瀏覽器緩存的解決方案,基本上在微信瀏覽器中都不出意外的沒有任何效果。更甚者不同的手機也用戶,緩存的嚴重程度也不太一樣。

要處理解決緩存問題,首先我們需要工具來驗證,我們的去除緩存的解決方案是否有效。我這裏能想到的最直觀的方式就是通過對手機抓包,將手機從微信瀏覽器發起請求後的完整鏈路有個直觀的展示。這裏我推薦windows用戶,可以使用Fiddler。後文也將結合該工具爲大家證明解決方案的有效性。

其次,我們對緩存進行分類,這裏將緩存分成兩大類:靜態資源、網絡請求。本文討論的是前者。
三、實踐過程

剛剛說了,常規的解決緩存的方案,都沒有效果。最簡單就是添加meta(無效):

接下來我們就先來分析下我們的應用組成。由於我們的應用是單頁程序,所有整個程序只要一個html文件,這裏就叫做index.html,在index.html中我們會加載對應的靜態資源。這也就是說,靜態資源的緩存就是指index.html文件和其內部引用的資源文件。那麼是index.html文件被微信瀏覽器緩存了,導致我們最新的程序功能沒有被及時的更新,還是index.html的內部引用的資源文件被緩存了呢?如果你的項目使用了打包工具,並且對資源文件的命名使用了混淆比如md5(vue-cli打包出的 靜態文件名稱都會被加上MD5串)。其中生成的原理大致就是根據你這個資源文件,生成的md5串,這個MD5串作爲你文件名稱的一部分。也就是說,資源文件的內容改變,對應的文件的md5必定也會改變,所以生成出來的文件名稱,也肯定會改變。如圖:

那麼很明顯,因爲內部引用的資源文件的緩存可能性很小,問題就在與我們的入口index.html文件。

資源請求場景-覆盤:

1.用戶通過微信端,第一次進入我們的單頁應用,瀏覽器正常向我們的nginx服務獲取資源。如圖:

通過抓包工具,我們攔截到手機正常向我們的服務請求資源。可以看到請求的狀態是result:200,body:1378 (正常請求)

2.那麼我們再一次向服務請求相同地址時候,同樣進行抓包,如圖:

再第二次進行請求的時候,我們發現請求的狀態是result:304,body:0(不重新獲取資源)

要詳細的瞭解還請自行查閱資料。這裏簡單說下狀態碼,304就表示:nginx告訴微信瀏覽器,我nginx上的index.html沒有變化,你微信可以從你原來的緩存裏面去找index.html的內容。然後微信就用了上一次請求的資源,不重新獲取新的資源了。

既然微信不再獲取新的資源了,所以你的新版本的代碼也就是在index.html文件的資源文件也就引用的路徑還是原來的路徑,如果你原來的index內部引用資源文件被刪除了,那麼會有兩種結果:1.這個時候請求可能會報錯,因爲資源文件找不到;2.瀏覽器之前緩存了這個文件,那麼你的代碼可以正常執行,只不過執行的是你原來的老版本的代碼。

注意:注意:注意:

這裏的304只是一個比方,具體微信再走緩存的場景也可能是其他的狀態碼或者其他情況,因爲博主一直多次進行版本迭代,反覆嘗試,沒有出現緩存的問題,所有這裏就拿304狀態簡單打了個比方。(後面有人能重新緩存問題,還請告知實際的情況)。

解釋下304狀態碼 :表示nginx上的index.html文件內容沒有改變,正常情況下,如果index.html文件被改變以後,nginx返回的狀態碼會變成200所以,微信端還是會發起新的請求獲取新的index.html。所以因爲文件沒有改變得到狀態碼304是正常的。

明確目的:

接下來我們的目標就明確了,

做到讓微信不從自己的緩存裏面去找index.html,或者說讓nginx,每次微信過來,都告訴微信,現在的index是最新的,微信要重新獲取。

假設我們通過訪問一個域名http://www.XXX.com(虛構的),該域名在就是訪問nginx配置的index.html。我們現在希望的效果是第一次訪問,微信會去獲取index.html的真實信息,第二次的時候,仍然是去獲取nginx的真實信息。

通過查閱相關資料後,最後我們發現我們只需要爲我們的nginx的配置下靜態文件index.html的緩存機制就行了。將html等文件類型的緩存類型設置成爲不緩存。如果是其他服務器,應該也是大同小異,修改各自服務器靜態資源的緩存策略。

nginx爲例就是設置

1. expires: -1;

2. add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";

    location ~ .*\.(?:htm|html)$ {
        expires      -1;
        add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }

在查閱資料中,最初發現可以通過只設置expires,結果在我的項目中不管用,後來就又加上了add_header Cache-Control這才解決。

我們通過抓包來驗證一下,現在多次訪問我們的單頁應用,會不會進行強制不緩存

在這裏我們發現,我們兩次通過公衆號的地址進入到我們的單頁應用時,每次都會重新觸發請求,現在就再也不怕緩存了,因此我們每次進來,微信都不會對我們的首屏頁面去做緩存了。在這裏我們需要注意的是,我們剛剛的配置,只是對html強制不緩存,但是對於我們index.html內的資源,我們沒有去做處理,原因就是前面說的,index內的引用資源如果改變,都會生成新的文件名稱,因此我們不需要擔心它的緩存問題。我們只要保證index.html的內容是最新的就OK了。

這裏補充兩點,1.細心的朋友可以看到我的配置裏面加入了root參數,因爲我們項目在nginx下設置了多套環境,每套項目的在不同的文件夾下,你如果只有一個環境,而且靜態資源是放在html文件夾下的,這裏可以忽略不寫。博主對nginx也不太懂,有些配置也不太清楚。2.可能有些朋友沒有使用打包工具,解決了index.html緩存問題,還有內部資源文件緩存的問題,這個問題你也可以通過nginx配置完成強制nginx不緩存js、image、css等等靜態資源。但是我沒有嘗試過這能不能達到讓微信瀏覽器不對這些文件進行緩存,也就是說,配置nginx能做的就是讓nginx告訴微信瀏覽器不要去緩存,微信瀏覽器到底聽不聽,我沒有去驗證過。但是,建議還是通過打包工具動態生成的好,少操心。
四、問題總結

抓包、抓包、抓包,重要的事情說三遍,有事沒事抓個包,將網絡數據的整個流程盡收眼底,會讓問題真實的暴露在你的眼前。可能有些同學覺得博主寫的過於繁瑣,不如直接說自己的解決方案。其實博主是覺得,也許我的解決方案可能更多的是適合於我項目的應用場景,我也更希望通過把我對這個問題的解決的過程描述清楚,也許解決過程中的某一個點,能給後面踩坑的同學一些小小的借鑑,那樣也是極好的。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章