測驗:從 Node.js 專案遷移到 Bun
共 5 題,點選答案後會立即顯示結果
1. 將 Node.js 專案遷移到 Bun 的第一步驟是什麼?
2. 在 Bun 中取得目前檔案的目錄路徑,應該使用什麼語法?
3. 當遷移後遇到 native module 載入錯誤時,以下哪個是正確的處理方式?
4. 在 Docker 中部署 Bun 應用,Dockerfile 的 FROM 指令應該使用哪個映像檔?
FROM ??? AS base
WORKDIR /app
5. 根據漸進式遷移策略,以下哪個是正確的遷移順序?
一句話說明
把現有的 Node.js 專案「搬家」到 Bun,享受更快的速度,同時處理可能遇到的相容性問題。
為什麼要遷移?
先問自己:遷移能帶來什麼好處?
| 情境 | 遷移效益 |
|---|---|
| 專案啟動時間太長 | Bun 冷啟動快 5-10 倍 |
| npm install 等很久 | bun install 快 10-20 倍 |
| 想用 TypeScript 但不想設定 | Bun 原生支援,零設定 |
| 專案大量使用 native modules | 可能不適合遷移 |
遷移前評估:相容性檢查清單
在動手之前,先檢查這些項目:
# 第一步:查看你的 dependencies
cat package.json | grep -A 100 '"dependencies"'
Code language: PHP (php)必看懂:高相容套件(可以放心遷移)
Express / Fastify / Hono # Web 框架
Prisma / Drizzle # 資料庫 ORM
Zod / Yup # 驗證
Lodash / Date-fns # 工具函式
Axios / node-fetch # HTTP 請求
Code language: PHP (php)需要注意:可能有問題的套件
bcrypt / argon2 # 有 native bindings
sharp # 圖片處理,需用 bun 版本
node-gyp 相關套件 # C++ 編譯的都要小心
Code language: PHP (php)快速檢查指令
# 檢查是否有 native modules
grep -r "node-gyp\|prebuild\|node-pre-gyp" node_modules/*/package.json
# 檢查 engines 欄位
cat package.json | grep -A 5 '"engines"'
Code language: PHP (php)實際遷移步驟
步驟 1:安裝 Bun
# macOS / Linux
curl -fsSL https://bun.sh/install | bash
# Windows(需要 WSL)
# 在 WSL 中執行上面的指令
# 確認安裝成功
bun --version
Code language: PHP (php)步驟 2:刪除舊的 node_modules 和 lock file
# 刪除舊的依賴
rm -rf node_modules
rm package-lock.json # npm 的 lock file
rm yarn.lock # yarn 的 lock file
rm pnpm-lock.yaml # pnpm 的 lock file
Code language: PHP (php)步驟 3:用 Bun 重新安裝
# Bun 會讀取 package.json,重新安裝所有依賴
bun install
Code language: CSS (css)執行後你會看到:
bun install v1.0.0
+ express@4.18.2
+ typescript@5.0.0
+ ... 其他套件
156 packages installed [524ms]
# ↑ 注意這個速度
Code language: CSS (css)步驟 4:修改 package.json 的 scripts
修改前(Node.js):
{
"scripts": {
"dev": "ts-node src/index.ts",
"start": "node dist/index.js",
"build": "tsc",
"test": "jest"
}
}
Code language: JSON / JSON with Comments (json)修改後(Bun):
{
"scripts": {
"dev": "bun run --watch src/index.ts",
"start": "bun run src/index.ts",
"build": "bun build src/index.ts --outdir dist",
"test": "bun test"
}
}
Code language: JSON / JSON with Comments (json)逐行解釋變化
"dev": "bun run --watch src/index.ts"
# ↑ 用 bun 執行
# ↑ --watch 檔案變更自動重啟
# ↑ 直接跑 TypeScript,不需要 ts-node
"start": "bun run src/index.ts"
# ↑ 生產環境也可以直接跑 .ts 檔
"test": "bun test"
# ↑ Bun 內建測試框架,不需要 Jest
Code language: PHP (php)步驟 5:測試是否正常運作
# 跑跑看開發模式
bun run dev
# 跑測試
bun test
# 如果有問題,看錯誤訊息
Code language: PHP (php)常見問題處理
問題 1:找不到模組
error: Cannot find module 'some-package'
Code language: JavaScript (javascript)解法:
# 重新安裝該套件
bun add some-package
# 如果還是不行,可能是 Node.js 專用模組
# 試試看安裝 polyfill
bun add @aspect-build/bazel-lib
Code language: PHP (php)問題 2:Native module 錯誤
error: dyld: Library not loaded...
# 或
error: Cannot load native module
Code language: PHP (php)解法:
# 方法 1:找 Bun 相容的替代套件
# 例如 bcrypt → bcryptjs(純 JS 實作)
bun remove bcrypt
bun add bcryptjs
# 方法 2:讓 Bun 重新編譯
bun add sharp --rebuild
Code language: PHP (php)問題 3:環境變數讀不到
// Node.js 寫法(在 Bun 也能用)
const port = process.env.PORT
// Bun 專屬寫法(更推薦)
const port = Bun.env.PORT
Code language: JavaScript (javascript)兩種都可以用,但 Bun.env 有更好的 TypeScript 型別支援。
問題 4:__dirname 和 __filename
// Node.js ESM 寫法
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
// Bun 寫法(簡單很多)
const __dirname = import.meta.dir
const __filename = import.meta.file
Code language: JavaScript (javascript)問題 5:測試框架不相容
// Jest 語法(部分相容,但建議改用 Bun 內建)
describe('math', () => {
it('adds numbers', () => {
expect(1 + 1).toBe(2)
})
})
// Bun 內建測試(語法幾乎一樣)
import { describe, it, expect } from 'bun:test'
describe('math', () => {
it('adds numbers', () => {
expect(1 + 1).toBe(2)
})
})
Code language: PHP (php)差別只在 import 來源,語法完全相容。
漸進式遷移策略
不確定要不要全面遷移?用這個策略:
階段 1:開發環境先試
# 只在本機用 Bun
bun install
bun run dev
# CI/CD 和生產環境還是用 Node.js
# 這樣出問題可以隨時退回去
Code language: PHP (php)階段 2:測試環境試跑
# 在測試環境部署 Bun 版本
# 觀察是否有問題
# 壓力測試比較效能
Code language: PHP (php)階段 3:灰度發布
# 只讓一部分流量走 Bun 版本
# 例如 10% 流量
Code language: PHP (php)階段 4:全面切換
確認沒問題後,再全面使用 Bun。
生產環境部署
Docker 部署
# Dockerfile
FROM oven/bun:1 AS base
WORKDIR /app
# 安裝依賴
FROM base AS install
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
# 複製原始碼並啟動
FROM base AS release
COPY --from=install /app/node_modules node_modules
COPY . .
EXPOSE 3000
CMD ["bun", "run", "src/index.ts"]
Code language: PHP (php)逐行解釋 Dockerfile
FROM oven/bun:1 AS base
# ↑ 使用官方 Bun 映像檔
# ↑ AS base 是多階段建構的命名
RUN bun install --frozen-lockfile
# ↑ 確保使用 lock file 的精確版本
CMD ["bun", "run", "src/index.ts"]
# ↑ 容器啟動時執行這個指令
Code language: PHP (php)Fly.io 部署
# 建立 fly.toml
fly launch
# 部署
fly deploy
Code language: PHP (php)fly.toml 範例:
[build]
dockerfile = "Dockerfile"
[http_service]
internal_port = 3000
force_https = true
[env]
NODE_ENV = "production"
Code language: JavaScript (javascript)Railway 部署
Railway 自動偵測 Bun 專案,只需要:
# 確保有 bun.lockb 檔案
bun install
# 推送到 GitHub,Railway 會自動部署
git push
Code language: PHP (php)何時該遷移?
適合遷移的情況
- 新專案或小型專案
- 主要是 API server 或工具腳本
- 想要更快的開發體驗
- 團隊願意學習新工具
不適合遷移的情況
- 大型單體應用,風險太高
- 大量使用 native modules
- 團隊沒有時間學習
- 穩定運行中,沒有效能問題
遷移決策流程圖
專案有效能問題嗎?
├─ 沒有 → 維持 Node.js,不用遷移
└─ 有 →
套件都相容嗎?
├─ 不確定 → 先在開發環境試用
└─ 相容 →
團隊有時間學習嗎?
├─ 沒有 → 維持 Node.js
└─ 有 → 開始遷移
Code language: CSS (css)Vibe Coder 檢查點
當你看到「Node.js 遷移到 Bun」的相關程式碼時,確認這些:
遷移前
# 有沒有 lock file?
ls bun.lockb # Bun 的 lock file
# package.json 的 scripts 改了嗎?
cat package.json | grep -A 10 '"scripts"'
Code language: PHP (php)遷移後
# 能正常啟動嗎?
bun run dev
# 測試有過嗎?
bun test
Code language: PHP (php)部署時
# Dockerfile 用的是 Bun 映像檔嗎?
FROM oven/bun:1 # 對
FROM node:18 # 錯,這還是 Node.js
Code language: PHP (php)完整遷移範例
假設有一個 Express 專案:
my-express-app/
├── package.json
├── package-lock.json
├── src/
│ └── index.ts
└── tests/
└── app.test.ts
遷移前
// package.json
{
"scripts": {
"dev": "ts-node-dev src/index.ts",
"test": "jest"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"ts-node-dev": "^2.0.0",
"jest": "^29.0.0",
"@types/express": "^4.17.0"
}
}
Code language: JSON / JSON with Comments (json)遷移指令
# 1. 刪除舊的
rm -rf node_modules package-lock.json
# 2. 用 Bun 安裝
bun install
# 3. 移除不需要的 devDependencies
bun remove ts-node-dev jest ts-jest @types/jest
Code language: PHP (php)遷移後
// package.json
{
"scripts": {
"dev": "bun run --watch src/index.ts",
"test": "bun test"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"@types/express": "^4.17.0"
}
}
Code language: JSON / JSON with Comments (json)測試檔案調整
// tests/app.test.ts
// 只需要改 import
import { describe, it, expect } from 'bun:test'
describe('GET /', () => {
it('returns hello', async () => {
const res = await fetch('http://localhost:3000/')
expect(res.status).toBe(200)
})
})
Code language: JavaScript (javascript)對 Vibe Coding 的幫助
學會這些遷移概念後,你可以:
- 更精準地下指令:當你請 AI 幫忙建立新專案時,可以明確指定「用 Bun 而非 Node.js」,並告訴 AI 專案是否有 native modules 的限制,讓 AI 選擇正確的套件
- 更有效地 Review AI 產出:看到 AI 生成的 package.json,能快速判斷 scripts 是否正確使用
bun run而非node,Dockerfile 是否使用oven/bun映像檔 - 更快速地除錯:遇到
Cannot find module或Cannot load native module錯誤時,知道這是遷移常見問題,能用本文的解法快速處理,而非讓 AI 反覆嘗試錯誤方向
本篇重點回顧
遷移評估:
├─ 檢查 dependencies 相容性
├─ 識別 native modules
└─ 評估團隊準備度
遷移步驟:
├─ 刪除 node_modules 和舊 lock file
├─ bun install 重新安裝
├─ 修改 package.json scripts
└─ 測試是否正常
常見問題:
├─ native modules → 找純 JS 替代
├─ 環境變數 → Bun.env
├─ __dirname → import.meta.dir
└─ Jest → bun:test
部署方式:
├─ Docker (oven/bun:1)
├─ Fly.io
└─ Railway
Code language: JavaScript (javascript)系列總結
恭喜完成【Bun 全面教學】系列!
回顧這四篇學到的:
| 篇章 | 主題 | 你學會了 |
|---|---|---|
| #01 | 快速入門 | 安裝、基本指令 |
| #02 | 內建功能 | 檔案操作、HTTP、SQLite |
| #03 | 套件管理 | bun install、workspace |
| #04 | 實戰遷移 | Node.js → Bun 完整流程 |
現在你已經具備:
- 閱讀 Bun 專案程式碼的能力
- 評估是否該用 Bun 的判斷力
- 必要時遷移專案的實戰技能
下一步建議:挑一個小型的個人專案,實際用 Bun 跑跑看!
進階測驗:從 Node.js 專案遷移到 Bun
測驗目標:驗證你是否能在實際情境中應用所學。
共 5 題,包含情境題與錯誤診斷題。
共 5 題,包含情境題與錯誤診斷題。
1. 你接手一個 Node.js 專案,想評估是否適合遷移到 Bun。你發現 package.json 中有以下依賴,哪個可能造成遷移困難? 情境題
{
“dependencies”: {
“express”: “^4.18.0”,
“prisma”: “^5.0.0”,
“bcrypt”: “^5.1.0”,
“zod”: “^3.22.0”
}
}
2. 你的團隊想嘗試 Bun,但對穩定性有疑慮。最適合的做法是什麼? 情境題
3. 你要將已遷移到 Bun 的專案部署到 Docker。以下哪個 Dockerfile 設定是正確的? 情境題
# 選項 A
FROM node:18 AS base
RUN npm install -g bun
# 選項 B
FROM oven/bun:1 AS base
RUN bun install –frozen-lockfile
# 選項 C
FROM alpine:latest AS base
RUN apk add bun
# 選項 D
FROM ubuntu:22.04 AS base
RUN curl -fsSL https://bun.sh/install | bash
4. 小明遷移專案到 Bun 後,執行 bun run dev 出現以下錯誤。最可能的原因是什麼? 錯誤診斷
$ bun run dev
error: Cannot load native module ‘bcrypt’
at node_modules/bcrypt/bcrypt.js:6:16
5. 小華將 Node.js 專案遷移到 Bun,但執行測試時所有 Jest 測試都失敗了。她的 package.json 如下,問題出在哪裡? 錯誤診斷
// package.json
{
“scripts”: {
“test”: “bun test”
}
}
// tests/math.test.ts
describe(‘math’, () => {
it(‘adds numbers’, () => {
expect(1 + 1).toBe(2)
})
})