每次訪問網(wǎng)頁,通常瀏覽器會(huì)從服務(wù)器下載所 需的資源,例如 HTML 文檔、圖片、CSS、JavaScript,甚至包括字體文件等。這里面的許多文件(例如圖片)都是很少變動(dòng)的,如果每次都要從服務(wù)器重新下載,會(huì)不必要 地增加網(wǎng)頁載入時(shí)間,同時(shí)也會(huì)對(duì)服務(wù)器造成一定壓力。通過合理配置緩存策略,可令瀏覽器以某種方式把這些靜態(tài)的文件緩存起來,下次請(qǐng)求同一資源時(shí),直接使 用本地存儲(chǔ)的副本,而不是從服務(wù)器重新下載。
啟用緩存至少有兩點(diǎn)顯而易見的好處:
- 減少頁面加載時(shí)間
- 減少服務(wù)器負(fù)載
瀏覽器是否使用緩存、緩存多久,是由服務(wù)器控制的。準(zhǔn)確來說,當(dāng)瀏覽器請(qǐng)求一個(gè)網(wǎng)頁(或者其他資源)時(shí),服務(wù)器發(fā)回的響應(yīng)的「響應(yīng)頭」部分的某些字段指明了有關(guān)緩存的關(guān)鍵信息。
?
Cache-Control
Cache-Control
HTTP 響應(yīng)頭是 HTTP 1.1 協(xié)議新增的指令,每個(gè)資源都可以通過設(shè)定 Cache-Control 來建立緩存策略。通常,可為它指定一個(gè)
max-age
,表示緩存的最長(zhǎng)時(shí)間,單位為秒。例如,若設(shè)定
Cache-Control: max-age=604800
,則表示這個(gè)資源的有效時(shí)間為 7 天。瀏覽器第一次獲取這個(gè)資源后,7 天之內(nèi)若再次請(qǐng)求,通常都不會(huì)與服務(wù)器進(jìn)行任何通信,而是直接使用本地副本。
此外,還可以為 Cache-Control 指定
public
或
private
標(biāo) 記。如果使用 private,則表示該資源僅僅屬于發(fā)出請(qǐng)求的最終用戶,這將禁止中間服務(wù)器(如代理服務(wù)器)緩存此類資源。對(duì)于包含用戶個(gè)人信息的文件(如一個(gè)包含用 戶名的 HTML 文檔),可以設(shè)置 private,一方面由于這些緩存對(duì)其他用戶來說沒有任何意義,另一方面用戶可能不希望相關(guān)文件儲(chǔ)存在不受信任的服務(wù)器上。需要指出的 是,private 并不會(huì)使得緩存更加安全,它同樣會(huì)傳給中間服務(wù)器(如果網(wǎng)站對(duì)于傳輸?shù)陌踩砸蠛芨?,?yīng)該使用傳輸層安全措施)。對(duì)于 public,則允許所有服務(wù)器緩存該資源。通常情況下,對(duì)于所有人都可以訪問的資源(例如網(wǎng)站的 logo、圖片、腳本等),Cache-Control 設(shè)為 public 是合理的。
?
Expires
同樣是用來控制緩存,
Expires
響 應(yīng)頭從另一個(gè)角度——指明緩存的具體過期日期,來控制資源何時(shí)過期。在過期時(shí)間以內(nèi),若再次發(fā)起請(qǐng)求,通常瀏覽器都不會(huì)與服務(wù)器進(jìn)行任何通信,而是直接使 用本地副本。Apache 服務(wù)器允許以多種方式,例如基于該資源的訪問時(shí)間或上次修改時(shí)間來設(shè)定 Expires 的值。注意,這里的時(shí)間一律使用格林威治時(shí)間(Greenwich Mean Time, GMT),而非本地時(shí)間。
當(dāng) Expires 和 Cache-Control 同時(shí)出現(xiàn)時(shí),通常后者會(huì)覆蓋前者的設(shè)定。由于 Expires 對(duì)用戶的系統(tǒng)時(shí)間有所依賴,因此通常認(rèn)為使用 Cache-Control 是更好的選擇(基本上所有的瀏覽器都支持 Cache-Control 指令)。
?
Last-Modified 和 ETag
服務(wù)器可在 HTTP 返回頭中包含
Last-Modified
字段或者
ETag
字段。Last-Modified 表示被請(qǐng)求資源在服務(wù)器端的上次修改時(shí)間,而 ETag 則是一個(gè)唯一文件標(biāo)識(shí)符,每次文件修改后都會(huì)生成一個(gè)新的 ETag。服務(wù)器通過向?yàn)g覽器發(fā)送這兩個(gè)字段,來告知瀏覽器其獲得的資源的版本。
無論通過 Cache-Control 還是 Expires 設(shè)置緩存,在過期時(shí)間以內(nèi),當(dāng)用戶點(diǎn)擊瀏覽器刷新按鈕時(shí),為了
確保
用戶所加載的資源是最新的,大部分瀏覽器不會(huì)再直接使用緩存中的數(shù)據(jù),而是發(fā)出一個(gè)條件請(qǐng)求(Conditional GET Request)。對(duì)于這類請(qǐng)求,瀏覽器會(huì)在請(qǐng)求頭中包含
If-Modified-Since
或
If-None-Match
字 段。前者即瀏覽器當(dāng)初得到的 Last-Modified;后者即瀏覽器當(dāng)初得到的 ETag。當(dāng)服務(wù)器發(fā)現(xiàn)資源的更新時(shí)間晚于 If-Modified-Since 所提供的時(shí)間,或者資源在服務(wù)器端當(dāng)前的 ETag 和 If-None-Match 提供的不符時(shí),會(huì)響應(yīng)整個(gè)資源,否則只會(huì)響應(yīng)一個(gè) 304 Not Modified 狀態(tài)碼(因此瀏覽器將不需要重新下載整個(gè)資源)。這種機(jī)制可以最大程度上減少數(shù)據(jù)下載量。此外,如果緩存的資源已過期,瀏覽器通常有兩種選擇:重新下載這 個(gè)資源,或發(fā)出一個(gè)條件請(qǐng)求。很多瀏覽器都會(huì)采取后者,以節(jié)約資源。
由于 Last-Modified 和 ETag 的作用是相同的(均為向服務(wù)器驗(yàn)證資源是否最新),因此只使用一個(gè)即可。通常認(rèn)為 Last-Modified 更好(它和 Expires 不同,由服務(wù)器生成,不依賴瀏覽器端時(shí)間)。
?
我的網(wǎng)站啟用緩存了嗎?
?
用瀏覽器的開發(fā)者工具或插件查看
為了確定是否啟用了緩存,只需要檢查服務(wù)器發(fā)回的「響應(yīng)頭」就可以。許多瀏覽器以及工具都可以檢查這些信息,我們以 Firefox 的插件 Firebug 為例。如圖所示:
下面再來看一個(gè)沒有啟用緩存的資源的例子:
沒有包含
Cache-Control
以及
Expires
信息。
?
在線檢測(cè)
也有一些方便的在線檢測(cè)服務(wù),用于對(duì)網(wǎng)站速度給出建議,其中就會(huì)檢測(cè)緩存設(shè)置情況。比如 Yahoo! 公司的 YSlow,以及 百度站長(zhǎng)工具 等,都有相應(yīng)的功能。大家可以去百度那里檢測(cè)一下,目前是不需要登錄即可檢測(cè)的。
?
使用緩存的策略
?
為靜態(tài)資源設(shè)置長(zhǎng)緩存時(shí)間
有些資源是很長(zhǎng)時(shí)間不會(huì)改變的,比如網(wǎng)站的 logo 圖片、jQuery 庫、字體等,因此可以為它們?cè)O(shè)定「永不過期」的緩存時(shí)間,例如設(shè)定為 10 年。
?
確保文件修改生效
有 些時(shí)候我們會(huì)修改一些資源,比如更新了 jQuery 版本,或網(wǎng)站的 CSS 樣式。如果這些資源已經(jīng)被緩存,那么除非用戶手工刷新頁面,否則要等緩存自然過期之后用戶才會(huì)獲得新版本。如何在這種情況下強(qiáng)制瀏覽器重新下載呢?最有效 的一個(gè)辦法就是在這類資源的文件名中包含版本信息,并在更改之后對(duì)應(yīng)地修改文件名。瀏覽器發(fā)現(xiàn)文件更換后,自然無法使用緩存,而會(huì)重新下載。
?
對(duì)于 HTML 文檔謹(jǐn)慎設(shè)定過期時(shí)間
大 部分情況下,對(duì)于其他圖片、CSS、JavaScript 等資源的請(qǐng)求都來自一個(gè)單一的 HTML 文檔。對(duì)于這類頁面通常應(yīng)該設(shè)定比較短的過期時(shí)間,或者干脆不設(shè)定。因?yàn)槿绻@類頁面被緩存,那么頁面中包含的資源的文件名等等信息都會(huì)一并被緩存,導(dǎo)致 對(duì)它的更新難以確保立即對(duì)用戶生效。
引用靜態(tài)資源時(shí),不要使用 Query String
Query String 就是例如
?key=val
的字符串,如
<script src="/static/js/func.js?v=a87ff8"></script>
?
這會(huì)阻止一部分較老的瀏覽器(包括 IE6 )對(duì)該資源進(jìn)行緩存。
?
設(shè)定緩存的方法
對(duì)于 Apache 服務(wù)器,可以通過
mod_expires
模塊來設(shè)定
Expires
HTTP 頭或
Cache-Control
HTTP 頭的
max-age
指令。編輯相應(yīng)目錄下的
.htaccess
文件,或直接對(duì) Apache 的配置文件(根據(jù)服務(wù)器系統(tǒng)版本不同,可能為
httpd.conf
或
apache2.conf
等)作出修改。
?
分文件類別設(shè)定
使用
ExpiresByType
可以按照文件的 MIME Type 設(shè)定某一類文件的過期日期。例如:
<IfModule mod_expires.c> ExpiresActive On ExpiresByType text/css "access plus 1 week" ExpiresByType application/javascript "access plus 2 weeks" ExpiresByType image/x-icon "access plus 6 months" ExpiresByType image/gif "access plus 6 months" ExpiresByType image/png "access plus 6 months" ExpiresByType image/jpeg "access plus 6 months" ExpiresByType video/x-flv "access plus 6 months" ExpiresByType application/pdf "access plus 6 months" </IfModule>
?
其中
access plus 1 week
表示將緩存過期設(shè)置為訪問時(shí)間(即當(dāng)前時(shí)間)之后的一周。如果將
access
替換為
modification
,則緩存過期會(huì)被設(shè)定為文件修改時(shí)間之后的一周。可以使用的時(shí)間單位包括:
- years
- months
- weeks
- days
- hours
- minutes
- seconds
不同的時(shí)間也可以進(jìn)行組合,例如:
ExpiresByType text/html "access plus 1 month 15 days 2 hours" ExpiresByType image/gif "modification plus 5 hours 3 minutes"
?
根據(jù)文件擴(kuò)展名進(jìn)行設(shè)置
如果希望根據(jù)擴(kuò)展名來指定緩存規(guī)則,可以使用
FilesMatch
配合正則表達(dá)式。為了簡(jiǎn)潔,我這里只規(guī)定了
ExpiresDefault
。它的優(yōu)先級(jí)很低,只會(huì)在對(duì)應(yīng)文件沒有任何其他規(guī)則能夠匹配(包括上層目錄下的緩存規(guī)則)時(shí)生效。
<IfModule mod_expires.c> <FilesMatch "\.(css|js)$"> ExpiresActive on ExpiresDefault "access plus 1 week" </FilesMatch> </IfModule>
?
對(duì)某些文件設(shè)定
同理,也可以對(duì)某些文件啟用特定的緩存策略。注意,文件名中的點(diǎn)(
.
)是需要轉(zhuǎn)義的。
<IfModule mod_expires.c> <FilesMatch "^(example\.css|example\.js)$"> ExpiresActive on ExpiresDefault "access plus 1 week" </FilesMatch> </IfModule>
?
對(duì)某一文件夾下的所有文件設(shè)定
對(duì)于靜態(tài)文件,一個(gè)比較方便的做法是將它們?nèi)糠诺揭粋€(gè)目錄下,并對(duì)該目錄下的所有文件設(shè)定。但是,此處需要注意防止其他規(guī)則將
ExpiresDefault
覆蓋掉。
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 10 years" </IfModule>
?
有用的工具及參考資料
- Cache-Control header checker (可檢測(cè)給定的地址是否啟用了 Cache-Control,還會(huì)教你如何設(shè)定)
- Caching Tutorial for Web Authors and Webmasters
- HTTP 緩存 - Web Fundamentals (來自 Google Developers)
- 百度站長(zhǎng)工具-頁面優(yōu)化建議
- h5bp/server-configs (HTML5 Boilerplate 提供了所有最流行的服務(wù)器的配置文件樣例)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
