﻿# 如何在 IIS 中將靜態檔案設定用戶端快取 (Client-side Cache)

當網站上線後，由於網站中許多靜態的網頁、圖檔、CSS、JavaScript 等資料都不會頻繁的變動，為了讓網頁的載入速度加快，我們通常都會將靜態檔案先設定 **用戶端快取** (Client-side Cache)，也就是所謂的 Expires Header 或稱 Cache Headers，這有別於我們在開發程式時所用的 **伺服器端快取** (Server-side Cache)。

在尚未做出任何調整的情況下，Browser 與 Web Server 之間是用以下機制幫你加快網頁載入速度的：

1\. 當瀏覽器第一次載入圖檔或其他靜態檔案時，IIS 會回傳 ETag 與 Last-Modified 這兩個 HTTP Header

![HTTP Headers](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/1e51c6693b12f6bc088a-image_3.png "HTTP Headers")

2\. 當瀏覽器第二次載入圖檔或其他靜態檔案時，瀏覽器就會傳送兩個特殊的 HTTP Header 給 IIS 伺服器，分別是 If-Modified-Since (如果檔案修改時間大於這個時間) 與 If-None-Match (如果伺服器的 ETag 不等於)，然後伺服器會根據瀏覽器送來的 HTTP Header 跟伺服器上的靜態檔案進行比對，若是條件符合的話，就代表伺服器上的檔案與本機的快取的版本不一樣，這時就會重新以 HTTP 200 回應新檔案。不過通常的狀況是檔案沒有做出任何變動，這時伺服器就會回應 HTTP 304 Not Modified 狀態，告知瀏覽器我不會回應檔案內容，僅有 HTTP Response Header 部分而已。

![HTTP Headers](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/9c0d617ca41d4a0c66d4-image_6.png "HTTP Headers")

\---

因為 Browser 不用下載檔案內容 (圖檔, CSS, JavaScript, ...)，因此網頁下載的速度提升了，不過這不是最好的結果，因為網頁每次要下載圖片時，都還是會發出 HTTP Request 並等待 HTTP Response 回應，如果我們利用規劃完善的 **用戶端快取** (Client-side Cache) 機制設定，那麼連 Browser 連 HTTP Request 都不會送出，而直接取用用戶端本機的快取檔案，這樣的頁面顯示速度最快！

如果要在 IIS6 中設定某一個目錄的**用戶端快取** (Client-side Cache) 機制設定，最簡單的作法就是設定 **HTTP 標頭** 頁籤的「啟用內容的到期限制」，如下圖示：

![設定 HTTP 標頭 頁籤的「啟用內容的到期限制」](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ca5490860402e64035bb-image_9.png "設定 HTTP 標頭 頁籤的「啟用內容的到期限制」")

如果你有多個目錄要執行快取的話，必須每個目錄都進行這類設定，例如：css, js, Content, .. 等目錄。

如果在 IIS7 下，那就更容易了，只要修改網站根目錄下的 web.config 檔，你可以找到 <system.webServer> 區段，並加入以下設定：

```
<staticContent>
    <clientCache cacheControlMaxAge="00:10:00" cacheControlMode="UseMaxAge"/>
</staticContent>
```

其中 cacheControlMaxAge 為 timeSpan，其格式為 d.hh:mm:ss，其中 d 是「天數」、hh 是小時、mm 是分鐘及 ss 是秒數，其中的天數是可省略的。這項設定沒有 GUI 介面可以協助你，必須手動設定。

\---

設定好之後，請清除所有瀏覽器快取，然後再測試看取得的 HTTP Response Header 有什麼變化：

![HTTP Headers](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ad655a6529b78ddaafd4-image_12.png "HTTP Headers")

快取之後，你在點選其他頁面時，這些被快取的靜態檔案都不會再次下載，你將會發現網頁顯示速度飛快，如果兩張網頁內容差不多的話，甚至會感覺不到瀏覽器有換頁的感覺。

\---

使用 **用戶端快取** 是有個致命的缺點，也就是當檔案已被下載快取後，若你的檔案在伺服器端被更新過，這時瀏覽器是完全不會收到更新通知的，要解決這個問題可以參考我另一篇文章：[簡易克服CSS 被瀏覽器快取(*Cache*)的問題](/post/2008/02/03/Avoid-browser-cache-problem-on-css-or-javascript-file)。

**相關連結**

-   [Static Content <staticContent>](http://www.iis.net/ConfigReference/system.webServer/staticContent)
-   [IIS 7.0: clientCache Element for staticContent (IIS Settings Schema)](http://msdn.microsoft.com/en-us/library/ms689443.aspx)
-   [IIS 7.0：設定 HTTP 到期回應標頭](http://technet.microsoft.com/zh-tw/library/cc770661\(WS.10\).aspx)
-   [加速前端網頁效能的14條規則](/post/2007/11/24/14-rules-for-faster-front-end-performance-notes)
