前端最佳化中很重要的一項是設定一個較長的到期時間,例如yahoo的expires設的是10年,page
speed推薦一個月以上。設expires的目的就是讓沒有更新的資源不應該產生http請求,如果強制產生請求則返回304,減少伺服器壓力和降低頻寬。exprires屬於伺服器最佳化範疇,需要修改伺服器配置並重啟。
http header相關知識
expires:指定緩衝到期GMT的絕對時間,如果設了max-age,max-age就會覆蓋expires。如果expires到期需要重新請求。
last-modified:WEB
伺服器認為對象的最後修改時間,比如檔案的最後修改時間,動態網頁面的最後產生時間。
ETag:就是一個對象(比如URL)的標誌值,就一個對象而言,比如一個 html 檔案,如果被修改了,其 Etag
也會別修改, 所以,ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 伺服器
判斷一個對象是否改變了。如果有多個伺服器需要考慮Etag同步問題。
比如前一次請求某個 html
檔案時,獲得了其 ETag,當這次又請求這個檔案時, 瀏覽器就會把先前獲得的 ETag 值發送給 WEB 伺服器,然後 WEB 伺服器會把這個 ETag
跟該檔案的當前 ETag 進行對比,然後就知道這個檔案有沒有改變了。
Cache-Control:
這個是http
1.1中為了彌補 Expires 缺陷新加入的,現在不支援http 1.1的瀏覽器已經很少了。
max-age: 指定緩衝到期的相對時間秒數,max-ag=0或者是負值,瀏覽器會在對應的緩衝中把Expires設定為1970-01-01
08:00:00 。
s-maxage: 類似於max-age,只用在共用快取上,比如proxy.
public: 通常情況下需要http身分識別驗證的情況,響應是不可cahce的,加上public可以使它被cache。
no-cache: 強制瀏覽器在使用cache拷貝之前先提交一個http請求到原始伺服器進行確認。這對身分識別驗證來說是非常有用的,能比較好的遵守
(可以結合public進行考慮)。它對維持一個資源總是最新的也很有用,與此同時還不完全喪失cache帶來的好處),因為它在本地是有拷貝的,但是在用之前都進行了確認,這樣http請求並未減少,但可能會減少一個響應體。
no-store: 告訴瀏覽器在任何情況下都不要進行cache,不在本地保留拷貝。
must-revalidate: 強制瀏覽器嚴格遵守你設定的cache規則。
proxy-revalidate: 強制proxy嚴格遵守你設定的cache規則。
用法舉例: Cache-Control: max-age=3600, must-revalidate
cache:使用本機快取,不發生請求。
304:通過If-Modified-Since
If-Match判斷資源是否修改,如未修改則返回304,發生了一次請求,但請求內容長度為0,節省了頻寬。
如果有多台負載平衡的伺服器,不同伺服器計算出的Etag可能不同,這樣就會造成資源的重複載入,我看的yahoo首頁就沒設Etag,估計有這麼方面的考慮。
下面我的一些分析,不敢說完全正確,只測試了IE6和FF3.5,感興趣的朋友一塊討論,畢竟瀏覽器對我來說是個黑洞。
下面主要說說expires,主要有這四個疑問
1.設定expires後,請求狀態應該是什麼樣的?是304還是cache?
2.如果資源被瀏覽器cache了,怎麼才能保證資源正確更新,尤其是頁面不出錯。
3.瀏覽器是否有差異?
4.到期時間設為多少比較好。
為瞭解決上面的疑惑,我用apche做了測試,apache的配置如下:
#載入expires模組<br />LoadModule expires_module modules/mod_expires.so<br />#取消Etag,去掉Etag帶來的幹擾<br />FileETag none<br />ExpiresActive On<br />ExpiresDefault "access plus 10 years"<br />ExpiresByType image/gif "access plus 10 years"<br />ExpiresByType image/jpeg "access plus 10 years"<br />ExpiresByType image/png "access plus 10 years"<br />ExpiresByType text/css "access plus 10 years"<br />ExpiresByType text/html "access plus 1 seconds"<br />ExpiresByType text/javascript "access plus 10 years"<br />ExpiresByType application/x-unknown-content-type "access plus 10 years"<br />ExpiresByType application/x-javascript "access plus 10 years"<br />
測試還需要考慮訪問頁面的方式,方式不同請求狀態也會有差異。開啟瀏覽器清除緩衝,然後開啟頁面進行測試,多次測試結果如下:
| 開啟頁面方式 |
IE6(httpwatch) |
FF3.5(httpfox) |
| 1. 第一次開啟頁面 |
200 |
200 |
| 2. 重啟瀏覽器開啟頁面 |
cache,即時發生資源修改也不會重新請求 |
cache,即時發生資源修改也不會重新請求 |
| 3. F5重新整理 |
304,發生修改的資源狀態為200 |
304,發生修改的資源狀態為200 |
| 4. Ctrl+F5重新整理 |
200,強制全新請求 |
200 |
| 5. 後退 |
cache,簡單直接地從緩衝載入 |
cache,簡單直接地從緩衝載入 |
| 6. 在已訪問頁面地址欄斷行符號 |
cache |
cache |
總結:
用yahoo首頁驗證了上面的結論,除yahoo F5重新整理頁面時IE6下有兩個請求狀態為cache外(目前沒分析到原因),二者基本一致。
把expires設為30天、14天結果頁一樣。有了上面的測試結果做expires最佳化心理就有底了,疑問1和3已解決。
第二種方式開啟頁面,有資源修改也走本機快取,極有可能出錯,問題2最穩妥的辦法是修改的資源啟用新名稱,yahoo的作法是檔案名稱後加版本號碼,這回增加前端的工作量。目前每次更新指令碼庫,資源地址都不變,主要為避免重新命名後相關應用都需要更新的問題,節省開發的時間。
expires設2,3天,有點短,穩定的應用的js css
img更新不是很頻繁,像yahoo設10年可以理解為永不到期,十年中網站不知道改版多少次了。最低設30天還比較合適。
參考資料:
http://www.360doc.com/content/08/0501/14/41237_1227846.shtml
http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.4
http://www.mnot.net/cache_docs/
楊建:網站加速--Cache為王篇 http://www.itlearner.com/article/4421
Caching in HTTP http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
Header
Field Definitions http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
age http://labs.apache.org/webarch/http/draft-fielding-http/p6-cache.html#header.age
Age Calculations http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html