Bun 1.4.2 要不要升級?先驗證 Elysia、AsyncLocalStorage 與 lockfile
Bun 1.4.2 是 2026 年 9 月的穩定更新,官方首頁列出的重點不是新語法,而是修正多個會直接影響建置、長時間執行和安裝流程的問題。其中兩項被明確標成 1.4.1 regression:bun build 在 Elysia 應用中錯誤重新命名區域變數,以及 AsyncLocalStorage 的 store 被不必要地保留。
直接答案是:如果你的專案使用 Elysia、AsyncLocalStorage、worker_threads、Bun.Image 或經常在 CI 執行 bun install,值得先在隔離分支升到 1.4.2 做針對性 smoke test;不要只看 bun —version,也不要把升級和 lockfile/package manager 遷移一次混做。
1.4.2 修了什麼,哪些專案優先驗證?
官方目前列出七項修正與 JavaScriptCore 升級。可以依你的實際使用面向排序:
| 變更 | 可能受影響的專案 | 升級後要測什麼 |
|---|---|---|
| bun build 不再把同一 block 的 var 錯誤改名成 let | Elysia 或依賴 Bun bundler 的應用 | production build、啟動與主要 route |
| AsyncLocalStorage 不再保留外層 store | request context、logger、trace、session middleware | nested run、exit、並行 request 和長時間記憶體 |
| worker_threads online 順序修正 | @discordjs/ws 或依賴 worker 初始訊息的程式 | online event、第一批 message、shutdown |
| JIT/GC crash 修正 | 長時間 process、musl container、壓力較高的服務 | soak test、RSS、crash log |
| Bun.Image 支援 CMYK/YCCK JPEG | 圖片轉檔、縮圖、上傳處理 | 不同色彩空間的 fixture 與輸出檢查 |
| JSON 錯誤行為一致 | 依賴 .json() 錯誤類型的 API | invalid JSON、錯誤邊界和 retry |
| bun install lockfile panic 修正 | lockfile hash 不一致或多 workspace CI | clean install、frozen lockfile、workspace |
「修正」不等於「所有相關 bug 都不存在」。例如 JIT 和 GC crash 是 rare path,應用程式仍需用自己的 runtime、平台和負載做驗證,不要把官方列出的修正解讀成完整的 stability guarantee。
先確認 binary、revision 和安裝來源
Bun 官方建議用 bun upgrade 更新 stable,並用 bun —version 和 bun —revision 確認 binary。升級前先記錄目前版本,方便在 CI 與本機比較:
bun --versionbun --revisionwhich bun如果 Bun 是透過 Homebrew、Scoop 或其他 package manager 安裝,就用同一個 package manager 更新;不要一邊讓 Homebrew 管理 binary,一邊執行 bun upgrade,否則下次套件更新可能覆蓋你的版本或讓 PATH 指向另一個 binary。
單機安裝的 stable 更新流程可以是:
bun upgradebun --versionbun --revision不要在 production host 上直接切 canary 來確認 bug 是否消失。canary 適合隔離環境做先行驗證,但它不等於 stable release,也會帶來另一組未知變更。
Elysia:先做 build diff,再啟動產物
如果你的 Elysia 專案使用 bun build,1.4.2 的回歸修正值得優先驗證。不要只看 build command 的 exit code,還要檢查產物能不能啟動並處理一條真實 route:
rm -rf .tmp-bun-142-distbun build ./src/index.ts --target bun --outdir .tmp-bun-142-distbun run .tmp-bun-142-dist/index.js上面的 entrypoint 和輸出檔名請換成自己的設定。測試重點包括:
- 同一個 block 內是否有依賴變數名稱或 closure 行為的程式碼。
- Elysia plugin、middleware 和 route 是否被 bundler 產出正確。
- production env、dynamic import 和 error handler 是否仍照預期。
- build 前後的 source map、artifact size 和啟動時間是否出現異常。
如果你是透過 framework script 產生 build,先把真正執行的 Bun command 印出來;bun run build 可能呼叫另一個 bundler,不能用它的成功代替 bun build regression test。
AsyncLocalStorage:測 nested context 與長時間生命週期
官方修正的是 exit() 和 nested run() 不再保留外層 store。這類問題很難用一次請求看出來,應該做一個最小測試再接到實際 logger/request context:
import { AsyncLocalStorage } from 'node:async_hooks'
const storage = new AsyncLocalStorage<{ requestId: string }>()
storage.run({ requestId: 'outer' }, () => { storage.run({ requestId: 'inner' }, () => { console.log(storage.getStore()?.requestId) })})真正的回歸測試還要覆蓋:
- request A 與 request B 並行時,context 不會交叉。
- nested run 完成後,外層 store 仍可用但不會無限保留短生命週期資料。
- exit() 後的 callback 不會讀到錯誤的 request context。
- 長時間壓測的 heap/RSS 沒有因 middleware store 持續增加。
不要只用 process.memoryUsage() 的單次數值判斷 memory leak 已修好;請固定 request pattern、跑足夠時間,並比較 1.4.1 和 1.4.2 的趨勢。
worker_threads:事件順序要用事件測,不要用 sleep 猜
1.4.2 修正 worker_threads 的 online 事件會先於 worker 第一批 message 抵達的順序。依賴初始化 handshake 的程式,應直接把順序寫成 assertion:
const events: string[] = []
worker.on('online', () => events.push('online'))worker.on('message', () => { events.push('message') if (events.length >= 2) { console.assert(events[0] === 'online') }})測試時不要用固定 setTimeout(100) 等待「應該已經 online」。正確做法是等待事件、設定 timeout 作為失敗保護,並測試 worker error、early exit、重啟和 shutdown。若應用程式使用 @discordjs/ws 或其他 event-driven library,還要跑一次實際 reconnect 流程。
lockfile panic:在乾淨工作目錄重現
如果你曾遇到 bun install 對 package-name hash 不一致的 lockfile panic,請不要在目前工作目錄直接刪 lockfile 來證明問題消失。先複製到暫存目錄或使用 CI 的 clean checkout:
git clone --no-local . /tmp/bun-142-checkcd /tmp/bun-142-checkbun --versionbun install --frozen-lockfilebun test實際專案若使用 Git worktree、private registry、workspace 或 patched package,要把相同的設定帶進測試。測試通過後再決定是否更新 lockfile;不要因為 Bun 1.4.2 能讀取現有 lockfile,就順便把 npm、pnpm、Yarn 和 Bun 的 lockfile 全部換掉。若團隊仍以 pnpm 為主,可以先參考pnpm 安裝時的 hardlink/copy fallback 排查,把 package manager 的責任邊界分開。
圖片、JSON 與 runtime crash 的小型 fixture
對其餘修正,使用固定 fixture 比用人工點選更容易回歸:
- 準備 CMYK/YCCK JPEG,確認 Bun.Image 可以解碼,並檢查輸出色彩與尺寸。
- 準備截斷 JSON 和錯誤 MIME response,確認 .json() 會得到預期 SyntaxError,且 retry 不會重複寫入資料。
- 在 glibc 與 musl container 各跑一次長時間 process,記錄 JIT/GC crash、RSS 和 exit code。
- 對 Date、Intl、TypedArray 的 hot path 跑現有效能基準;JavaScriptCore 升級後不要假設結果完全相同。
這些測試的目的,是確認你的程式能從修正中受益,而不是重做 Bun 官方完整測試套件。遇到差異時,保留 Bun version、revision、OS、CPU、lockfile、最小 reproduction 和完整 stderr,才容易交叉比對。
上線前的升級矩陣
可以用以下順序把 Bun 1.4.2 放進團隊流程:
- 在隔離 branch 更新單一 CI job 的 Bun binary。
- 跑 clean install、type-check、unit test、build 和主要 route smoke test。
- 對 AsyncLocalStorage、worker_threads、圖片和 JSON 依實際使用面向補 regression。
- 做一次 staging soak test,觀察 memory、crash、log 和 request latency。
- 用 bun —revision 寫進 build metadata,確定 production 實際跑的是驗證過的 binary。
- 若使用外部 package manager,確認它的 lockfile 與 cache 行為沒有被一併改動。
結論:以受影響路徑決定升級範圍
Bun 1.4.2 的價值在於修正幾個會讓 production 很難排查的 regression:Elysia build rename、AsyncLocalStorage memory leak、worker event ordering、JIT/GC crash 和 lockfile panic。升級時先確認 binary 來源與 revision,再按你的實際使用面向跑 targeted smoke test;不要只把版本字串改成 1.4.2,也不要同時把整個 package manager 流程改掉。這樣即使升級後仍有問題,你也能知道是 runtime、bundler、lockfile 還是部署層。
常見問題
Q: Bun 1.4.2 要直接在 production 執行 bun upgrade 嗎?
A: 不建議。先在隔離 branch 和 staging 驗證,再把固定 version/revision 放進 image 或 build metadata。若 Bun 由 Homebrew、Scoop 等 package manager 管理,應用同一個來源更新。
Q: Elysia 沒有使用 bun build,也需要測同一個 regression 嗎?
A: 優先級較低。先確認你的 framework script 實際呼叫哪個 bundler;如果 production build 不是 bun build,就把測試重點放在你真正使用的 build pipeline,再針對 runtime 相關修正做 smoke test。
Q: lockfile panic 修好後可以順便換成 Bun lockfile 嗎?
A: 不建議把兩件事綁在一起。先用 1.4.2 驗證既有 workflow,再另開一個 migration 變更討論 lockfile、workspace、registry、CI cache 和 rollback,避免出問題時無法分辨原因。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。