From bed0326bfb66a158c15eead47bf825027d6df573 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 10 Sep 2026 07:04:13 +0000 Subject: [PATCH] =?UTF-8?q?js=20/=20css=20=E6=94=B9=E6=88=90=E6=AF=8F?= =?UTF-8?q?=E6=AC=A1=E9=87=8D=E6=96=B0=E9=A9=97=E8=AD=89=EF=BC=8C=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E5=AE=8C=E5=B0=B1=E4=B8=8D=E6=9C=83=E5=86=8D=E5=90=83?= =?UTF-8?q?=E5=88=B0=E8=88=8A=E6=AA=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 檔名沒有內容雜湊,卻給了 max-age=600 —— 部署完的十分鐘內,已經開過網頁的人 拿到的仍是舊檔,而且瀏覽器連問都不問伺服器。 今天被這件事咬了不只一次:修好的東西明明上線了,畫面還是舊行為,於是往程式碼 裡找一個根本不存在的 bug。最後一次是「在 0G Storage 上查看」仍然連到已經被 刪掉的 /file/ —— repo 裡早就沒有那段程式碼了。 改成 max-age=0, must-revalidate。這不等於不快取:檔案沒變時伺服器回 304, 內容不重傳,只多一次很小的往返;這幾支檔案都只有二三十 KB。 vendor/ 底下是釘死版本的第三方 bundle(合計約 1MB,內容不會變),改成長快取 加 immutable,反而比原本沒有規則時更好。 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015NBxaWtzqEX3i8NvoZEeq3 --- public/_headers | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/public/_headers b/public/_headers index 3f53c7f..2bdf0ae 100644 --- a/public/_headers +++ b/public/_headers @@ -1,13 +1,27 @@ -# 靜態資源可以快取,但 index.html 要每次重新驗證,改版才會立刻生效。 +# 檔名沒有內容雜湊,所以 js / css 一律每次重新驗證。 +# +# 原本這兩類是 max-age=600。那表示部署完之後的十分鐘內,已經開過網頁的人 +# 拿到的仍是舊檔 —— 而且瀏覽器連問都不會問伺服器。這在展示的時候害慘過我們: +# 修好的東西上線了,畫面卻還是舊行為,於是往程式碼裡找一個根本不存在的 bug。 +# +# must-revalidate + max-age=0 不等於不快取:檔案沒變時伺服器回 304, +# 內容不會重傳,只多一次很小的往返。這幾支檔案都只有二三十 KB, +# 拿這點成本換「部署完就是最新的」很划算。 +# +# vendor/ 底下是釘死版本的第三方 bundle(合計約 1MB),內容不會變, +# 維持長快取。 /js/* - Cache-Control: public, max-age=600 + Cache-Control: public, max-age=0, must-revalidate /css/* - Cache-Control: public, max-age=600 + Cache-Control: public, max-age=0, must-revalidate /index.html Cache-Control: public, max-age=0, must-revalidate +/vendor/* + Cache-Control: public, max-age=604800, immutable + /* X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin