本文是Web前端性能優化系列文章中的第五篇,主要講述內容:配置ETag。完整教程可查看:Web前端性能優化
什麼是ETag?
實體標簽(EntityTag)是唯一標識瞭一個組件的一個特定版本的字符串,是web服務器用於確認緩存組件的有效性的一種機制,通常可以使用組件的某些屬性來構造它。
條件GET請求
瀏覽器下載組件的時候,會將它們存儲到瀏覽器緩存中。如果需要再次獲取相同的組件,瀏覽器將檢查組件的緩存時間,假如已經過期,那麼瀏覽器將發送一個條件GET請求到服務器,服務器判斷緩存還有效,則發送一個304響應,告訴瀏覽器可以重用緩存組件。
那麼服務器是根據什麼判斷緩存是否還有效呢?答案有兩種方式,一種是前面提到的ETag,另一種是根據最新修改時間。先來看看最新修改時間。
最新修改時間
原始服務器通過Last-Modified響應頭來返回組件的最新修改時間。
以一個實際例子來說明,當我們不帶緩存訪問.hk的時候,我們需要下載google的logo,這時會發送這樣一個HTTP請求:
Request:
GET /logo.png HTTP 1.1
Host: .hk
Response:
HTTP 1.1 200 OK
Last-Modified:Wed, 09 Oct 2013 01:35:39 GMT
當需要再次訪問相同組件的時候,同時緩存已經過期,瀏覽器會發送如下條件GET請求:
Request:
GET /logo.png HTTP 1.1
If-Modified-Since:Wed, 09 Oct 2013 01:35:39 GMT
Host: .hk
Response:
HTTP 1.1 304 Not Modified
實體標簽
ETag提供瞭另外一種方式,用於檢測瀏覽器緩存中的組件與原始服務器上的組件是否匹配。摘抄自書上的例子:
不帶緩存的請求:
Request:
GET /i/yahoo/gif HTTP 1.1
Host: us.yimg.com
Response:
HTTP 1.1 200 OK
Last-Modified:Tue,12 Dec 200603:03:59 GMT
ETag:10c24bc-4ab-457elc1f
再次請求相同組件:
Request:
GET /i/yahoo/gif HTTP 1.1
Host: us.yimg.com
If-Modified-Since:Tue,12 Dec 200603:03:59 GMT
If-None-Match:10c24bc-4ab-457elc1f
Response:
HTTP 1.1 304 Not Midified
當ETag和Modified-Time都出現瞭,則原始服務器禁止返回304除非請求中的條件頭字段全部一致。
為什麼要引入ETag?
ETag主要是為瞭解決Last-Modified無法解決的一些問題:
1.一些文件也許會周期性的更改,但是他的內容並不改變(僅僅改變的修改時間),這個時候我們並不希望客戶端認為這個文件被修改瞭,而重新GET;
2.某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改瞭N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME隻能精確到秒);
3.某些服務器不能精確的得到文件的最後修改時間。
ETag帶來的問題
ETag的問題在於通常使用某些屬性來構造它,有些屬性對於特定的部署瞭網站的服務器來說是唯一的。當使用集群服務器的時候,瀏覽器從一臺服務器上獲取瞭原始組件,之後又向另外一臺不同的服務器發起條件GET請求,ETag就會出現不匹配的狀況。
最佳實踐
1. 如果使用Last-Modified不會出現任何問題,可以直接移除ETag,google的搜索首頁則沒有使用ETag。
2. 確定要使用ETag,在配置ETag的值的時候,移除可能影響到組件集群服務器驗證的屬性,例如隻包含組件大小和時間戳。
完整教程可查看:Web前端性能優化