Cloudflare 在 2026 年 11 月 2 日公告:JavaScript Workers 使用 2026-11-17 或更新的 compatibility date 時,將預設切換到新的 module registry,不必再手動加入 new_module_registry flag。Python Workers 繼續使用舊 registry;既有 JavaScript Worker 只要沒有更新 compatibility date 或變更 flag,也不會在 11 月 17 日突然被切換。

這不是 Cloudflare Workers 舊版全面退場,也不是到期日一到所有網站都必須修改。真正的遷移時點是團隊下一次把 compatibility_date 提高到 11 月 17 日或之後並部署。Cloudflare 用 compatibility date 隔離可能不相容的 runtime 行為,因此升級日期應像依賴版本一樣進 code review,而不是由工具自動改成今天後直接上線。

新 registry 改變的是模組解析,不只是多幾個 API

新 registry 以 URL 語意解析 module specifier,支援 import.meta.url、import.meta.main 與 import.meta.resolve(),並讓 Node.js compatibility 下的 require() 載入 ES module 時更接近 Node.js 行為。Cloudflare 9 月的技術文章也說明,新實作會延後到第一次 import 才編譯 module,並改善不同載入路徑的錯誤一致性。

相容性風險集中在三類。第一,import attributes 現在會驗證:未知 key、不支援的 type,或宣告 type 與實際 module 不符,都可能直接拋錯。第二,require() 載入 ES module 時,回傳內容可能和舊 registry 的 default export 解包方式不同。第三,只要被 require() 的 module graph 含有 top-level await,呼叫就會失敗,即使該 module 先前已經完成 evaluation;這類依賴應改用動態 import()。

此外,bundler 可能在上傳前改寫 import.meta 或把多個 module 合併。程式在本機 Node.js 成功,不代表 Worker 上的實際 bundle 行為相同;反過來,只看原始 TypeScript 也看不出 Wrangler 最後上傳了什麼。

先做依賴盤點,再在舊日期主動試用

先搜尋程式與 lockfile 中的 CommonJS/ESM 邊界:require() 指向 ES module、使用 top-level await 的 package、JSON 或其他非 JavaScript module 的 import attributes,以及依賴 import.meta 的 build plugin。也要檢查自訂 build、Vite、Wrangler plugin 與 monorepo 共用套件,因為它們可能在 application code 之前就改寫 module graph。

不要直接把 production 的 compatibility date 改到 11 月 17 日。Cloudflare 官方提供的安全試法,是先保留原日期,在 staging 加入 new_module_registry。對同一個 commit 建立舊 registry 與新 registry 兩個版本,執行 API contract、scheduled event、queue consumer、Durable Object binding 與例外處理測試;若有多個 entrypoint,每個都要覆蓋。

可先用 npx wrangler deploy --dry-run --outdir dist 檢查實際輸出,確認 module 是否被 inline、specifier 是否被改寫,以及額外檔案是否真的包含在 bundle。接著用與正式環境相同的 Wrangler、Vite plugin 或 Vitest integration 執行測試,避免本機工具鏈與部署工具鏈使用不同 runtime 行為。

驗收清單要包含失敗案例

功能測試至少覆蓋啟動、第一個 request、冷啟動後的 lazy import、動態 import、JSON module、CommonJS dependency 與錯誤路徑。若應用以 require() 載入 ES module,加入斷言確認拿到的是預期 namespace 或 export,而不是只驗證「沒有 throw」。若 dependency graph 有 top-level await,應把載入方式改為 await import(),再驗證初始化不會跨 request 留下未完成狀態。

針對 import attributes,準備正確 JSON type 與故意錯誤 type 的測試;新 registry 應拒絕錯誤宣告。這能確認 staging 確實跑到新行為,而不是測試設定遺漏 flag。使用 import.meta.resolve() 時,也要知道它只解析 URL,不會確認目標 module 存在,更不會從網路下載 dependency。

部署時採小流量或版本化發布,監看 startup exception、module not found、top-level await 與 import attribute 相關錯誤。升級前記錄目前錯誤率與啟動時間,升級後只比較相同流量和版本;不要從一次短暫觀察推論效能提升。官方技術文章描述架構優勢,不等於每個專案都有固定百分比改善。

回滾與長期選擇

若正式環境出現無法立即修正的相容性問題,可以在 2026-11-17 之後的 compatibility date 加上 legacy_module_registry 暫時保留舊行為,或回到上一個已驗證的 Worker version。回滾時要同時保存 code、compatibility date、flags 與工具版本;只回復程式碼但保留新 runtime 設定,可能仍會失敗。

長期而言,使用 Node.js 生態套件、需要標準 URL module resolution 或 import.meta 的專案,應完成遷移,而不是永久停在舊日期。暫時 opt out 的團隊要建立 issue、owner 與移除日期,並把阻擋套件鎖定到可追蹤版本。Cloudflare 說舊 compatibility date 仍受支援,但文件通常以新行為為主,維持舊 registry 的理解與測試成本只會逐步增加。

最穩健的順序是:在舊日期用 flag 試跑、檢查 bundle、修正 CJS/ESM 邊界、以版本化流量驗證,最後才更新 compatibility date。11 月 17 日是預設值改變的分界,不應被誤當成所有 Worker 同時停機的期限。