wrangler.jsonc 的 routes 是宣告式的完整清單,不是增量。少列一個網域,deploy 就會連同 DNS 記錄一起刪掉。
發布於 2026-08-30・約 3 分鐘
那天我在 Worker 上新增三個自訂網域。改設定、wrangler deploy、看到 Success!,然後網站整個斷線——不只新的三個,連本來好好的 apex 和另外 29 個子網域全滅。
wrangler deploy
Success!
wrangler.jsonc 原本長這樣,30 幾個網域一路列下來:
wrangler.jsonc
{ "name": "room", "main": "worker.js", "routes": [ { "pattern": "example.com", "custom_domain": true }, { "pattern": "a.example.com", "custom_domain": true }, { "pattern": "b.example.com", "custom_domain": true } // …還有 30 行 ] }
我要加三個新的。腦子裡想的是「deploy 一下把新網域註冊上去」,於是把 routes 改成只有那三個新的:
routes
"routes": [ { "pattern": "x.example.com", "custom_domain": true }, { "pattern": "y.example.com", "custom_domain": true }, { "pattern": "z.example.com", "custom_domain": true } ]
我當時的心智模型是「這次 deploy 要處理的網域」。錯得很徹底。
routes 是宣告式的完整狀態,不是這次要新增的清單。wrangler 把它當成「這個 Worker 應該綁定的網域,全部就這些」,然後去對齊現況:
於是那 30 個沒被我列進去的網域,全部被判定為「應該移除」。
更痛的是 custom_domain: true 的拆除語意。它不只解除 Worker 綁定——Cloudflare 的自訂網域是綁定加 DNS 記錄的組合,拆掉綁定會把對應的 DNS 記錄一起刪掉。所以不是「網站回到沒有 Worker 的狀態」,是那些網域在 DNS 層直接不存在了。
custom_domain: true
wrangler deploy 全程回報成功。從它的角度看,它確實忠實執行了我宣告的狀態。
沒有一鍵復原。DNS 記錄刪掉就是刪掉了。
做法是把完整的 30 幾筆 routes 補回設定檔,重新 deploy,讓 wrangler 反向再建一次。綁定和 DNS 記錄會重新長出來,但要等 DNS 傳播,實際恢復是分鐘級不是秒級。
deploy
在 Cloudflare 儀表板上手動一個一個加也可以,但三十幾個網域用點的,出錯機率比改設定檔還高。
一、把血淚寫在檔案最上面。 不是寫在 README,是寫在你下次會打開的那個檔案的第一行:
{ // ⚠⚠ routes 是「唯一真相」的完整清單,不是增量。 // 不在清單裡的自訂網域會被 deploy 自動拆除,連 DNS 記錄一起刪。 // 新增網域時務必「保留全部舊的、再加新的」。 "routes": [ /* … */ ] }
二、deploy 前先看 diff。 只要動到 routes,先確認這次的改動是「只有新增,沒有減少」:
git diff wrangler.jsonc | grep '^-' | grep pattern
有輸出就停下來想清楚。少一行是有意的嗎?
三、「成功」不等於「對」。 這是最貴的一課。wrangler deploy 印出 Success! 的意思是「你宣告的狀態已經套用完成」,不是「網站現在是好的」。這兩件事在宣告式工具裡差得很遠。
現在我 deploy 完一定實際抓一次線上:
curl -sI https://example.com | head -1 curl -s https://example.com | grep -o '<title>[^<]*'
看到真的回 200、真的是新版的標題,才算部署完成。
任何吃「完整清單」的宣告式設定,都有同一個形狀的陷阱:Terraform 的 resource、Kubernetes 的 manifest、雲端供應商的安全群組規則。共通點是省略等於刪除,而人類讀設定檔時的直覺是「這裡寫的是我要改的東西」。
分辨方法很簡單:問自己「如果我把這個欄位整個刪掉,會發生什麼?」如果答案是「對應的資源會被移除」而不是「維持現狀」,那它就是宣告式的完整狀態,不能只寫增量。
標籤:Cloudflare Workers、wrangler、事故