觀點 · 資訊分享

Cloudflare Workers 的 fetch() 新增 cf.vary:同一個網址有多語言、多格式版本,快取可以逐次指定

Cloudflare 在 6/28 讓 Workers 的 fetch() 支援 cf.vary 選項,可以針對單一子請求決定要怎麼處理來源回傳的 Vary 標頭:把相近的值併成同一份快取、照原值分版本,或乾脆不快取。

發布
2026-06-28
篇幅
約 4 分鐘 · 1,886 字
結構
7 節 + 3 題常見問題
標籤
#Cloudflare#Workers#快取#Vary 標頭
Cloudflare Workers 的 fetch() 新增 cf.vary:同一個網址有多語言、多格式版本,快取可以逐次指定

一句話看懂:Cloudflare Workers 的 fetch() 在 6 月 28 日多了 cf.vary 選項,同一個網址依語言或格式回不同內容時,可以每次請求各自決定快取怎麼分版本。

Workers fetch() 新增 cf.vary資訊圖卡:同網址有多語言或格式時,能每次請求各自決定怎麼存快取

先用白話講:Vary 是什麼?

想像一家報攤,同一份報紙有中文版和英文版,封面看起來一樣,書報架上卻要分開放。店員要知道客人要哪一版,才能拿對。

網路上也一樣:同一個網址,伺服器可能依照「瀏覽器偏好的語言」回中文或英文,或依照「想要的格式」回網頁或 JSON。伺服器會在回應裡加一個 Vary 標頭,告訴快取:「這個網址要依照某某標頭分版本放」。

發生什麼事

Cloudflare 在 6 月 28 日的更新日誌宣布:Workers 的 fetch() 請求現在支援 cf.vary 選項,用來控制 Cloudflare 對「帶有 Vary 標頭的來源回應」如何快取,而且只作用在這一次子請求。

官方範例是:預設不快取,但對 accept 與 accept-language 兩個標頭做整理。

三種處理動作

對每個出現在來源 Vary 裡的標頭,可以選一種動作:

動作 做法 適合
normalize 把意思相同的值整理成同一個快取版本 Accept、Accept-Language 這類常見標頭
passthrough 依原始值分版本,並原樣轉給來源 每個值的差異都有意義時
bypass 只要這個標頭出現在 Vary,就不快取 每個使用者都不同、或可能的值太多時

給開發者的技術細節

官方範例(Workers):

export default {
  async fetch(request) {
    return fetch(request, {
      cf: {
        vary: {
          default: { action: "bypass" },
          headers: {
            accept: {
              action: "normalize",
              media_types: ["text/html", "application/json"],
            },
            "accept-language": {
              action: "normalize",
              languages: ["en", "fr", "de"],
            },
          },
        },
      },
    });
  },
};

Workers 文件的說明(以下為文件目前版本,可能已經比 6/28 當天多了內容):

  • default 是必填,用來處理沒有列在 headers 裡的其他 Vary 標頭;headers 的名稱要小寫
  • accept 的 media_types 最多 10 項、accept-language 的 languages 最多 20 項、headers 最多 50 項
  • 設定不合法的話,那一次請求會忽略 cf.vary;來源回應若是 Vary: *,一律不快取
  • 來源的回應必須帶有 Vary 標頭,這個設定才會影響快取鍵
  • 官方建議:多數情況 default 用 bypass,替預期會出現的 Vary 標頭逐一設定,accept 與 accept-language 用 normalize

後續

7 月 2 日 Cloudflare 另外宣布,Cache Rules 也能直接依來源的 Vary 標頭分版本快取,這是整個網站層級的設定。文件說明兩者並存時,cf.vary 優先處理這一次子請求。

我的看法

做多語言網站,最常見的兩種做法:把語言放在網址路徑(/zh、/en),或同一個網址依瀏覽器的語言偏好回不同內容。前者對快取最友善;後者很方便,但以前要放上 CDN 快取就很麻煩,只能不快取、或自己想辦法分版本。

cf.vary 補的是「我在 Worker 裡想精準控制」的情境。我會用的原則是:預設保守(bypass),只對自己確定會變、值也有限的標頭開 normalize。否則 Accept-Language 這種標頭的寫法千變萬化,列不完整反而讓快取命中率變差,甚至不小心把不同使用者的內容快取在一起。上線前記得用不同語言的請求各測一次。

名詞小辭典

  • Vary 標頭:來源伺服器告訴快取「同一個網址要依哪些請求標頭分版本」的說明。
  • 快取鍵(Cache Key):快取用來判斷「這是不是同一份內容」的依據。
  • 子請求(Subrequest):Worker 在處理請求的過程中,向其他地方再發出的請求。
  • normalize(正規化):把意思相同、寫法不同的值整理成同一種寫法。

資料來源

常見問題

Vary 標頭是什麼?
是網站伺服器回應裡的一個提示,告訴快取:「同一個網址,我會依照請求的某些標頭回不同內容」,例如依 Accept-Language 回不同語言,依 Accept 回網頁或 JSON。快取就必須把這些標頭也算進分版本的依據。
cf.vary 跟整個網站的快取規則有什麼不同?
cf.vary 只影響一次 fetch() 子請求。官方文件說,如果同時有網站層級的 Vary 設定,cf.vary 優先。沒有設定 cf.vary 時,就依網站原本的 Vary 行為。
normalize 到底做了什麼?
把意思相同但寫法不同的標頭值整理成同一個快取版本。例如 Accept-Language: en-US, fr;q=0.8 與 fr;q=0.8, en-GB 這類只是排序或細節不同的寫法,可以對到同一份快取,提高命中率。
LINE