先分清網頁與靜態檔案

一家小型網店修改結帳按鈕、樣式表,以及顯示送貨選項的程式。顧客眼中這是同一次更新,瀏覽器卻會分別請求不同網址,各自套用快取規則。若所有回應都用同一設定,新版 HTML 可能配上舊程式,舊版 HTML 亦可能仍指向已刪除的檔案。第一步是列出回應種類,包括公開網頁、CSS、JavaScript、商品圖片、字型,以及載入後再取得的資料。逐項寫明同一網址的內容會否原地改變。這個性質比「靜態」的名稱更重要。

MDN 分別說明瀏覽器快取與共用快取,並指出 Cache-Control 控制回應何時可儲存及重用。所有訪客看見相同內容的商品圖片,與帳戶頁面是兩種不同情況。本文只討論公開靜態檔案,不為個人化回應提供快取政策。逐個網址確認由原站、內容傳遞網絡,或兩者提供;亦要查明原站更新後,CDN 會否保留舊副本。若網址不變,而先前快取的回應仍屬有效,瀏覽器無從知道伺服器檔案已有新內容。因此,發佈流程必須明確處理檔案身分與版本。

一份簡短設計記錄已足夠:「HTML 每次重新驗證;建置檔名帶內容版本;過渡期間保留舊版檔案。」這是可供本地採用的政策示例,並非所有網站通用的標頭處方。它讓開發者、寄存服務商和驗收人員理解同一套機制,也會揭露例外:例如員工經常覆蓋同一路徑的公開圖片。這類圖片改動時應換網址,或採用較短的有效期並接受更多驗證請求。不要把會原地變動的圖片套上為不可變建置檔案準備的長有效期。

讓檔案網址對應固定內容

對建置時產生的檔案,可在網址加入內容雜湊值或其他會隨內容改變的版本。新版樣式表可稱為 shop.8f2c.css,舊版為 shop.4a91.css;這些名稱只是示例,不是任何網站的實際發佈紀錄。檔案內容改變,網址就要改;內容沒有變,網址可以維持。MDN 稱此為快取破除。只有在回應的有效期內確實不會覆蓋同一網址,較長的 max-age 及 immutable 才有理據。只在網址加日期,卻繼續覆蓋同一個帶日期檔案,仍會破壞這項承諾。

版本管理要涵蓋互相依賴的一組檔案。若 HTML 指向新版 JavaScript,卻仍使用舊樣式表,就要核對兩者是否兼容。程式若會延遲載入其他檔案,應先確認那些檔案已上載,再讓頁面指向它們。使用建置清單把邏輯檔名對應至帶雜湊值檔名時,先發佈檔案,再發佈引用它們的 HTML。舊版檔案要保留一段足以讓仍開着舊頁面的訪客完成操作的時間;確實日數須按網站使用模式和回退需要決定。部署時一次過刪除全部舊檔,會使稍後才載入的程式片段失效。

不要把清除 CDN 快取的按鈕當作主要版本機制。受管理的快取或可清除內容,但 MDN 指出,HTTP 快取一般沒有由原站刪除所有既存副本的通用方法。即使 CDN 清除成功,顧客瀏覽器內仍屬有效的副本也不會因此消失。清除操作可作事故補救,但需要另行驗證;日常發佈則依靠新網址。若寄存平台會改寫或忽略網址查詢字串,宜改用檔名雜湊值,並在實際邊緣節點測試,不要假設原站設定原封不動送到訪客。

讓舊訪客取得新的檔案對應

HTML 網頁是告訴瀏覽器應取哪一版檔案的地圖。對會更新的公開網頁,Cache-Control: no-cache 可要求快取重用前先向伺服器驗證;它並不代表禁止儲存。MDN 明確區分 no-cache 與 no-store。如有 ETag 或 Last-Modified 等驗證資訊,內容未變時可回傳 304,而毋須重傳整頁。實際政策須配合寄存服務的行為。若網站是靜態產生,除了具名頁面,也要檢查提供相同 HTML 的備用路由;兩條路徑若有不同 CDN 規則,整套安排便可能失效。

以一次示例發佈說明:中午顧客打開商品頁,頁面引用 app.A.js 及 style.A.css。十二時十分,團隊先上載 app.B.js 和 style.B.css,確認兩者能正常讀取,然後才把商品頁 HTML 改為指向 B。之後重新開頁的顧客經驗證會取得 B 的對應;一直保留中午分頁的顧客則可能仍執行 A,稍後才請求另一個 A 的片段,所以 A 必須暫時保留。更新 HTML 不會倒流修改已開啟的分頁。若同時更改 API,伺服器還須在過渡期間兼容兩版客戶端。

CDN 可能再加一層規則。檢查顧客實際使用的網域上的標頭及快取行為,不要只看原站網址。邊緣節點可能改動 Cache-Control,或從另一位置提供檔案。記錄哪一層負責設定標頭、CDN 有否覆寫,以及預覽或測試環境與正式環境有何差異。驗收人員應能指出 HTML 版本、沿着其中的檔案網址檢查,並確認那些網址的內容與建置結果一致。瀏覽器強制重新載入會繞過部分正常快取路徑,不能單憑它證明一般回訪顧客也看到相同結果。

實測回訪與回退

測試應在部署前開始。先用一般瀏覽器設定檔打開正式頁面,讓公開檔案進入快取;之後部署一項可看見但無風險的變更,再以同一設定檔正常導覽。透過開發工具查看 HTML 請求、實際引用的檔案網址、回應狀態、Cache-Control,以及檔案來自記憶體、磁碟或網絡。若 CDN 各地節點可能不同,可再以另一裝置經公開網域檢查。記下觀察到的確實網址及回應。這比一句「快取正常」更有用,因為能分辨問題是舊 HTML、遺失的片段,還是標頭設錯。

回退也要同樣測試。若 HTML 回復引用 A,A 的檔案必須仍可讀取,且內容維持原樣;把 A 內容塞進 B 檔名會違反網址與內容一一對應的規則。新開頁面與原有分頁都要檢查。若有錯誤的公開檔案已用長有效期及 immutable 派發,應產生修正版新網址並更新 HTML,而非覆蓋舊網址的內容。CDN 清除可作輔助,卻無法保證清除所有瀏覽器副本。決定採用長有效期之前,應先把這項補救步驟寫入發佈清單。

發佈後宜安排簡短覆核,而非永遠照抄設定。檢查清理程序有否刪去舊分頁仍會引用的檔案,也要避免員工可原地編輯的圖片誤放入不可變建置路徑。把設定值與公開網域實際取得的回應比較。若網站使用 service worker,它本身還有快取和更新週期,需要另行審視;本文的 HTTP 方法不能取代那項工作。具體驗收準則是:回訪顧客導覽時取得當前 HTML,當中所有公開檔案均存在且內容固定,而保留舊頁面的顧客也可完成手上操作。

進行前先確認

  • 我們能否指出哪些公開網址的內容會原地改變?
  • HTML 會否重新驗證,而帶雜湊值檔案在過渡期間維持可用及內容不變?
  • 有否在正式網域實測一般回訪、保留舊分頁及回退?

資料來源及延伸閱讀