開發前端時,怎麼 Mock API 最省事又有效?(MSW+NextJs)
2023-11-111.52Front EndMSWReact
有時候後端還沒寫完,但前端要先衝一波,這時候「Mock API」就很重要啦。到底怎麼 mock 最順手?這邊分享三種常見的方式,看看哪一種最適合你:
直接抓本地 JSON 文件
最基本的做法就是放個 fakeData.json
然後用 fetch()
抓。很簡單,超適合剛開始開發時用。
// fakeData.json [ { "id": 1, "name": "Fake Item 1" }, { "id": 2, "name": "Fake Item 2" }, { "id": 3, "name": "Fake Item 3" } ]
// 使用fetch呼叫本地JSON文件 fetch('fakeData.json') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error fetching data:', error));
優點是快、不用裝工具,開了檔案就能跑。但它也真的就只是讀檔,不能做 POST、PUT 之類的,也沒辦法模擬錯誤或延遲。只能說,是很臨時的解法。
本地 Server(像 json-server)
你可以用 json-server
或是自己開個 Express server,這就有點像假的後端,前端能照著真的 API 去串。
更多詳情請參考 json-server 官方文檔。
npm install -g json-server json-server --watch db.json --port 3001
優點就是你可以模擬 GET、POST、PUT、DELETE,甚至還能故意加個延遲。
缺點嘛,就是需要開一個 server,有時候還要改 port,可能會跟你本來的 dev server 打架。而且多了個工具,團隊其他人也要一起裝。
攔截請求,像 MSW 這種做法
這個我個人最推薦。用 MSW (Mock Service Worker) 去攔截瀏覽器發出的請求,直接在 client 端就模擬出 response。你可以模擬成功、失敗、延遲等狀況,還能搭配測試使用。
下面我進一步介紹它的用法
MSW 的使用與設置
安裝 MSW
npm i msw --save-dev npx msw init public/ --save //在目錄下設置假server
本文章版本 1.x ,當前 msw 最新版已是 2.x,注意以下操作僅使用於 Next page router client 端呼叫 API
文件結構
建立一個 mocks
資料夾來存放相關配置和假資料:
mocks/ ├── dummy-data.ts # 存放模擬資料 ├── handlers.ts # 定義假 API 處理邏輯 ├── browser.ts # 瀏覽器環境設置 ├── server.ts # 測試環境設置 └── index.ts # 初始化檔案
1. 假資料文件
dummy-data.ts
// 這個檔案存放模擬的所有假資料 export const cars = [{ name: '勞斯萊斯' }]
2. 假 API 處理邏輯
handler.ts
// 放置所有假API import { rest } from 'msw' import * as fake from './dummy-data' export const handlers = [ rest.get('/cars', (req, res, ctx) => { return res( ctx.json(fake.cars) ) }), rest.post('/new-car', (req, res, ctx) => { return res( ctx.status(201), ctx.json({ message: 'success' }) ) }) ]
3. 瀏覽器環境
browser.ts
// 瀏覽器開發用 import { setupWorker } from 'msw' import { handlers } from './handlers' export const worker = setupWorker(...handlers)
4. 測試環境
server.ts
// 跑測試用、在node環境執行 import { setupServer } from 'msw/node' import { handlers } from './handlers' export const server = setupServer(...handlers)
5. 初始化檔案
index.ts
// 這個檔案用以區分當前是供"測試用"還是"開發時模擬API用" const IS_BROWSER = typeof window !== 'undefined' export const setupMocks = async () => { if (IS_BROWSER) { const { worker } = await import('./browser') worker.start() } else { const { server } = await import('./server') server.listen() } }
以我們公司來說,開發會分成三種開發環境 :
- 本地假資料
- 遠端假資料
- 正式環境
在等待後端 API 開發完成前,我們可以使用第一種本地假資料進行開發。
利於開發環境,可以在 package.json 這樣做:
"scripts": { "dev": "next dev", // 遠端假資料 "mock-api-dev": "cross-env NEXT_PUBLIC_API_MOCKING=true next dev", //本地假資料 }
安裝 cross-env
套件,用以設置環境變數,設 :
NEXT_PUBLIC_API_MOCKING=true
NextJs 中, html 的 server 端渲染與 msw api 攔截註冊發生 race condition,官方有提供解法異步載入 service worker,只有在頁面掛載完成後才啟用。
我們再自行改造一下,寫成 HOC 的形式包裹住 App 主組件,其中 NEXT_PUBLIC_API_MOCKING 用來區分當前環境,決定是否進行 API 攔截
import React, { useEffect, useState } from 'react' import { AppProps } from 'next/app' const mockingEnabled = process.env.NEXT_PUBLIC_API_MOCKING === 'true' || process.env.NODE_ENV === 'development' const withMocking = <T extends {}>( WrappedComponent: React.ComponentType<T> ) => { return (props: T) => { const [shouldRender, setShouldRender] = useState(!mockingEnabled) useEffect(() => { if (mockingEnabled) { import('@/mocks').then(async ({ setupMocks }) => { await setupMocks() setShouldRender(true) }) } }, []) if (!shouldRender) return null return <WrappedComponent {...props} />; } } function App({ Component, pageProps }: AppProps) { return ( <Component {...pageProps} />; ) } export default withMocking(App)
希望這篇優化的文章能讓你更清楚如何有效利用 MSW 與 Mock API!