處理了一個 Chrome 問題,因江湖經驗不足,多花了點時間搞定,筆記備忘。

測試台網站更新後,使用者回報版面還是錯的,但從我的機器看則正常。先懷疑是 Cache 問題,但按了 F5 重新載入甚至重啟 Chrome 仍無法解決。增加兩個對照組:使用者改用無痕模式以及用另一位同事 Chrome 的檢視結果與我相同,至此判定測試網站 OK,是使用者 Chrome 有問題。

電話遙控使用者按 F12 檢查 Console 錯誤訊息及 Network 看有無出現 404、500 HTTP 狀態,是否所有傳輸結果都是 200,回報並無異樣,只能現場勘察。

親自看了 F12 Network,很快發現異樣,HTML 內容回傳 304,其餘 js、css、png 則清一色是 200,明顯是 Cache 問題(以前使用者可能看到一大片 200 沒留意第一條不同)。但問題來了,依我的理解,IIS 對靜態檔提供 If-None-Match,If-Modified-Since 雙重快取檢查,檔案修改日期或內容異動都會觸發重新下載,為什麼會看到舊檔?(延伸閱讀:IIS HTML 檔 Cache 行為觀察)

我平時測試會開 F12 並勾選 Disable cache (如下圖),因此不會看到 Cache 舊版很合理;對照組同事之前沒有連過這個網站,所以沒有 Cache 可用;而開啟無痕視窗時不會引用 Cache。如此就能解釋了我們觀察到結果。

但我的疑問是:檔案修改理論上 ETag 會變,IIS 不該回傳 304,而又為何只有 HTML 是 304,其他檔案是 200。

回家在筆電弄了測試,還真的重現 HTML 304,css、png、js 200 的結果:

但我才注意到,200 的字是灰色的,Size 欄位則註明 (memory cache),代表瀏覽器未發送請求,自己做主用了記憶體 Cache 內容。觀察 HTML、css、png、js 傳回的 Response Header 只有設 ETag 跟 Last-Modified,沒有 Cache-Control,不應有此差異:

所以是 Chrome 對 HTML 跟 css/js/png 有差別待遇?

依據 HTTP 1.1 協定 13.4,當未指定 Cache-Control 時,快取系統「可以」將成功的回應內容存成 Cache 項目,並「可以」不必驗證是否新鮮就回傳 Cache 內容,也「可以」驗證新鮮度後回傳 Cache 內容。

Unless specifically constrained by a cache-control (section 14.9) directive, a caching system MAY always store a successful response (see section 13.8) as a cache entry, MAY return it without validation if it is fresh, and MAY return it after successful validation.

換言之,要送出 Request 得到 304,或完全不管伺服器端有沒有改直接用快取,瀏覽器有權自由決定;而由觀察結果,看起來 Chrome 的做法是 HTML 一律用 If-None-Match,If-Modified-Since 向伺服器查詢,css、js、png 等檔案在一段時間內可跳過詢問伺服器步驟直接用 Cache。隔一段時間後則會重新向伺服器驗證,全都為 304 (如下圖):

問題在按 Shift-F5 跳過 Cache 強制載入新版後排除。至於為什麼 HTML 檔案有動,IIS 仍傳回 304 卻也因現場被破壞不可考,只能等下回遇到再重啟調查。

由這次案例,我又多了解一些 Chrome/Edge 的 Cache 行為,但最重要的心得是 - 下回懷疑 Cache 問題,請使用者先 Shift-F5 就對了。

Observation of Chrome's cache behavior difference for static files like html, js, css, and Shift-F5 shortcut key tips.


Comments

# by 毛豆

是不是 iis 針對資料夾設定了快取時間?

# by 毛豆

另外 chrome 要真正清除快取順便重載,要使用 ctrl+shift+R

# by Jeffrey

to 毛豆,若設快取時間會有 Cache-Control 或 Expires Header 才對,參考:https://blog.darkthread.net/blog/aspnet-outputcache-experiment/ 另外,文章裡 Shift-F5 連結的 Google 文件提到 Shift + F5 鍵或 Ctrl + Shift + R 鍵 二者等效,都是「重新載入目前的網頁,略過已快取的內容」

# by Cash

而又為何只有 HTML 是 403,其他檔案是 200 => 這裡的 403 應該是 「304」

# by Jeffrey

to Cash, 錯字大王又一次正常發揮 orz 謝謝

# by 無名

感謝訊息提供(筆記)

Post a comment