如何切換 Mock 到真實 API
本指南說明如何從開發環境的 Mock API 切換到連接真實後端。
前置條件
- 已完成基於 Mock API 的開發
- 後端 API 已部署並可存取
方法一:環境變數切換
步驟 1:設定環境變數
# .env.development(Mock API)
VITE_USE_MOCK=true
VITE_API_BASE_URL=
# .env.staging(真實 API)
VITE_USE_MOCK=false
VITE_API_BASE_URL=https://api-staging.example.com
# .env.production(生產 API)
VITE_USE_MOCK=false
VITE_API_BASE_URL=https://api.example.com
步驟 2:條件啟動 MSW
// src/main.tsx
async function enableMocking() {
if (import.meta.env.VITE_USE_MOCK === 'true') {
const { worker } = await import('./mocks/browser');
return worker.start({
onUnhandledRequest: 'bypass',
});
}
}
enableMocking().then(() => {
createRoot(document.getElementById('root')!).render(<App />);
});
步驟 3:啟動不同環境
# 使用 Mock API
npm run dev
# 連接 Staging API
npm run dev -- --mode staging
# 連接生產 API(本地測試)
npm run dev -- --mode production
方法二:漸進式切換
一次切換一個 API,降低風險。
步驟 1:在 Handler 中添加旁路
// src/mocks/handlers/products.ts
import { http, passthrough } from 'msw';
const USE_REAL_API = import.meta.env.VITE_REAL_PRODUCT_API === 'true';
export const productHandlers = [
http.get('/api/v1/products', () => {
if (USE_REAL_API) {
return passthrough(); // 轉發到真實 API
}
// Mock 回應
return HttpResponse.json(mockProducts);
}),
];
步驟 2:逐一啟用
# .env.development
VITE_REAL_PRODUCT_API=true # 商品用真實 API
VITE_REAL_ORDER_API=false # 訂單仍用 Mock
VITE_REAL_CUSTOMER_API=false # 客戶仍用 Mock
方法三:完全移除 MSW
生產環境可完全移除 MSW。
步驟 1:條件載入
// src/main.tsx
async function bootstrap() {
// 只在開發環境載入 MSW
if (import.meta.env.DEV && import.meta.env.VITE_USE_MOCK !== 'false') {
const { worker } = await import('./mocks/browser');
await worker.start({ onUnhandledRequest: 'bypass' });
}
createRoot(document.getElementById('root')!).render(<App />);
}
bootstrap();
步驟 2:排除打包
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
external: import.meta.env.PROD ? ['msw'] : [],
},
},
});
常見問題
API 路徑不一致
Mock 和真實 API 路徑可能不同,使用 axios 攔截器處理:
// src/services/api.ts
const api = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || '',
});
// 路徑轉換
api.interceptors.request.use((config) => {
if (import.meta.env.VITE_USE_MOCK !== 'true') {
// 真實 API 使用 /api/v1 前綴
config.url = `/api/v1${config.url}`;
}
return config;
});
認證機制不同
Mock 使用簡化的 JWT,真實 API 可能有不同機制:
// src/services/auth.ts
export const authService = {
login: async (credentials) => {
if (import.meta.env.VITE_USE_MOCK === 'true') {
// Mock 登入
return api.post('/auth/login', credentials);
}
// 真實 OAuth2 流程
return oauthLogin(credentials);
},
};
資料格式差異
使用轉換層統一資料格式:
// src/services/transformers/product.ts
export function transformProduct(raw: any): Product {
return {
id: raw.id || raw.productId,
name: raw.name || raw.productName,
price: Number(raw.price),
// ...
};
}
驗證清單
切換前確認:
- 所有 API 端點都有對應的真實 API
- 認證流程已測試
- 錯誤處理已更新
- 資料格式轉換已完成
- CORS 設定正確