Cache-Control 全參數解析
Cache-Control 是 HTTP 快取的核心標頭。本篇將詳細解析每個指令的含義與使用場景。
一、 基本語法
1.1 格式
http
Cache-Control: directive1, directive2, directive31.2 分類
| 類別 | 指令 |
|---|---|
| 可快取性 | public, private, no-cache, no-store |
| 過期時間 | max-age, s-maxage, max-stale, min-fresh |
| 重新驗證 | must-revalidate, proxy-revalidate |
| 其他 | no-transform, immutable |
二、 可快取性指令
2.1 public
允許任何快取(包括 CDN)儲存回應:
http
Cache-Control: public, max-age=86400適用場景:
- 完全公開的資源
- 所有用戶看到相同內容
2.2 private
只允許瀏覽器快取,禁止共享快取(如 CDN):
http
Cache-Control: private, max-age=3600適用場景:
- 用戶專屬內容(個人資料、購物車)
- 包含敏感資訊的回應
javascript
// 個人資料
app.get("/api/profile", (req, res) => {
res.set("Cache-Control", "private, max-age=300");
res.json(userProfile);
});2.3 no-cache
允許快取,但每次使用前必須驗證:
http
Cache-Control: no-cache> `no-cache` 不是「不快取」!而是「每次都要驗證」。
2.4 no-store
完全禁止儲存,每次都要重新下載:
http
Cache-Control: no-store適用場景:
- 極度敏感的資料(銀行交易、密碼)
- 需要即時更新的內容
javascript
// 銀行交易
app.get("/api/transactions", (req, res) => {
res.set("Cache-Control", "no-store");
res.json(transactions);
});2.5 比較表
| 指令 | 允許儲存 | 需要驗證 | 適用場景 |
|---|---|---|---|
| public | ✅ 所有快取 | ❌ | 公開資源 |
| private | ✅ 僅瀏覽器 | ❌ | 用戶專屬 |
| no-cache | ✅ | ✅ 每次 | 需要驗證 |
| no-store | ❌ | - | 敏感資料 |
三、 過期時間指令
3.1 max-age
快取有效期(秒):
http
Cache-Control: max-age=3600 # 1 小時
Cache-Control: max-age=86400 # 1 天
Cache-Control: max-age=31536000 # 1 年3.2 s-maxage
專門給共享快取(CDN)使用,優先級高於 max-age:
http
Cache-Control: public, max-age=60, s-maxage=600- 瀏覽器:60 秒
- CDN:600 秒
3.3 max-stale
客戶端願意接受過期的快取:
http
# 請求標頭
Cache-Control: max-stale=3600表示願意接受過期不超過 1 小時的回應。
3.4 min-fresh
要求回應至少還有指定時間的新鮮度:
http
# 請求標頭
Cache-Control: min-fresh=600只接受至少還有 10 分鐘有效期的快取。
四、 重新驗證指令
4.1 must-revalidate
過期後必須向伺服器驗證,不能使用過期快取:
http
Cache-Control: max-age=3600, must-revalidate如果伺服器無法連線,直接返回錯誤,而不是使用過期快取。
4.2 proxy-revalidate
與 must-revalidate 類似,但只對共享快取生效:
http
Cache-Control: max-age=3600, proxy-revalidate4.3 stale-while-revalidate
允許在背景重新驗證時使用過期快取:
http
Cache-Control: max-age=60, stale-while-revalidate=3600優點:用戶不用等待,體驗更好。
4.4 stale-if-error
伺服器錯誤時使用過期快取:
http
Cache-Control: max-age=3600, stale-if-error=86400如果重新驗證時伺服器返回 5xx 錯誤,可以使用最多 24 小時前的過期快取。
五、 其他指令
5.1 no-transform
禁止中間代理修改回應:
http
Cache-Control: no-transform防止代理:
- 壓縮圖片
- 轉換編碼
- 修改內容
5.2 immutable
表示資源永遠不會變更:
http
Cache-Control: max-age=31536000, immutable效果:即使強制刷新也不會重新驗證。
適用場景:
- 帶 hash 的靜態資源
app.abc123.js
六、 常見組合
6.1 帶 hash 的靜態資源
http
Cache-Control: public, max-age=31536000, immutable- 1 年快取
- CDN 可快取
- 強制刷新也不驗證
6.2 HTML 文件
http
Cache-Control: no-cache或
http
Cache-Control: max-age=0, must-revalidate每次都驗證,確保獲取最新版本。
6.3 API 回應
http
# 公開 API,短期快取
Cache-Control: public, max-age=60
# 私有 API
Cache-Control: private, max-age=300
# 敏感 API
Cache-Control: no-store6.4 CDN 優化
http
Cache-Control: public, max-age=60, s-maxage=86400, stale-while-revalidate=600- 瀏覽器:1 分鐘
- CDN:1 天
- 過期時用戶不用等
七、 Express 實作
7.1 中介軟體
javascript
function cacheControl(options) {
const {
maxAge = 0,
sMaxage,
isPublic = false,
noCache,
noStore,
immutable,
} = options;
return (req, res, next) => {
const directives = [];
if (noStore) {
directives.push("no-store");
} else if (noCache) {
directives.push("no-cache");
} else {
directives.push(isPublic ? "public" : "private");
directives.push(`max-age=${maxAge}`);
if (sMaxage !== undefined) {
directives.push(`s-maxage=${sMaxage}`);
}
if (immutable) {
directives.push("immutable");
}
}
res.set("Cache-Control", directives.join(", "));
next();
};
}
// 使用
app.use(
"/assets",
cacheControl({
maxAge: 31536000,
isPublic: true,
immutable: true,
})
);
app.use("/api", cacheControl({ noCache: true }));7.2 按路由設定
javascript
// 靜態資源
app.get("/assets/*", (req, res, next) => {
res.set("Cache-Control", "public, max-age=31536000, immutable");
next();
});
// HTML
app.get("*.html", (req, res, next) => {
res.set("Cache-Control", "no-cache");
next();
});
// 敏感 API
app.get("/api/account", (req, res) => {
res.set("Cache-Control", "no-store");
res.json(account);
});八、 Nginx 配置
nginx
# 帶 hash 的靜態資源
location ~* \.[a-f0-9]{8}\.(js|css|png|jpg|gif)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
# 一般靜態資源
location ~* \.(js|css|png|jpg|gif)$ {
add_header Cache-Control "public, max-age=86400";
}
# HTML
location ~* \.html$ {
add_header Cache-Control "no-cache";
}
# API
location /api/ {
add_header Cache-Control "no-cache";
}總結
| 指令 | 說明 | 常見場景 |
|---|---|---|
| public | 允許所有快取 | CDN 資源 |
| private | 只允許瀏覽器 | 用戶資料 |
| no-cache | 每次驗證 | HTML |
| no-store | 禁止儲存 | 敏感資料 |
| max-age | 有效期 | 所有資源 |
| s-maxage | CDN 有效期 | CDN 優化 |
| immutable | 永不變更 | 帶 hash 檔案 |
| stale-while-revalidate | 背景更新 | 效能優化 |
> **黃金法則**:
- 帶 hash →
max-age=1y, immutable - HTML →
no-cache - API → 根據敏感度選擇
進階挑戰
- 設計一個完整的快取策略,區分不同類型的資源。
- 測試
stale-while-revalidate,觀察背景更新行為。 - 研究各瀏覽器對
immutable的支援程度。