mswjs:在瀏覽器和 Node 環(huán)境中輕松做 API Mocking

mswjs 是一個(gè)同時(shí)兼容瀏覽器和 Node 的 API mocking 庫,幫助開發(fā)者在 API 還沒 ready 的情況下,通過 mock 數(shù)據(jù)進(jìn)行完美開發(fā)。
mswjs 原理(瀏覽器端)是使用 Service Worker API 攔截(網(wǎng)絡(luò)層)實(shí)際請求實(shí)現(xiàn) API 的請求、響應(yīng)模擬。
官網(wǎng)地址:https://mswjs.io/
下面我們會創(chuàng)建一個(gè) Next.js 項(xiàng)目,來演示 mwsjs 的使用。
定義 mocks
按照約定,我們將 mock 定義放在 src/mocks
目錄中:
Mocking API
mwsjs 支持兩種類型的 API Mock,一個(gè)是 REST API,一個(gè)是 GraphQL API。如果你知道兩者的區(qū)別,或者壓根就不知道 GraphQL,也沒有關(guān)系,無腦看成 ?REST API 就行,因?yàn)槲覀?99.9% 的項(xiàng)目都是用 REST API。
我們編輯 handlers.js
:
rest
就是一個(gè)服務(wù)器(類似 express()
),用于處理請求和響應(yīng),我們下面分別介紹。
Request handler
假設(shè)我們要做一個(gè)基礎(chǔ)的登錄功能。需要準(zhǔn)備兩個(gè)接口:
POST /login
:登錄使用GET /user
:現(xiàn)在登錄用戶信息
先創(chuàng)建請求處理器 Request handler,使用 rest[METHOD]
方式:
handlers.js
文件是通過一個(gè)叫 handlers
的命名導(dǎo)出暴露攔截的/要 Mock 的請求的。
Response resolver
前一步已經(jīng)做到請求攔截了,這一步我們在 Mock 響應(yīng)數(shù)據(jù):
響應(yīng)回調(diào)函數(shù)接受 3 個(gè)參數(shù):
req
:匹配請求的信息res
:用于創(chuàng)建模擬響應(yīng)的功能函數(shù)ctx
:包含一系列用于設(shè)置模擬響應(yīng)的狀態(tài)碼、頭部、正文等功能的函數(shù)
整合
當(dāng)然,上面這些約定 Mocking API 寫好之后,并不會自動生效,我們還需要整合到現(xiàn)有項(xiàng)目中。
當(dāng)然,這塊我們根據(jù)瀏覽器端、Node 端分別介紹。
瀏覽器端
準(zhǔn)備
Mock Service Worker ?在客戶端是通過 Service Worker 做請求攔截的,因此這塊我們要單獨(dú)啟動個(gè)服務(wù)器服務(wù) 來自 mwsjs Service Worker 文件中的代碼請求 。
這塊代碼不需要我們手寫,直接使用 npx msw init <PUBLIC_DIR> --save
指令就可以了。這里的 <PUBLIC_DIR>
就是指項(xiàng)目的靜態(tài)資源的存放目錄,對 Next.js 來說,就是項(xiàng)目跟路徑下的 public/
目錄:
執(zhí)行完成后,會在 public/
下,看到多出一個(gè) mockServiceWorker.js
文件。mockServiceWorker.js
不需要我們做任何修改,放在這里就行了。這個(gè) worker 腳本會被注入到瀏覽器網(wǎng)頁中,用于攔截請求。
注意,這里的 --save
是必須的,這個(gè)選項(xiàng)會在 package.json
文件中寫一個(gè) msw
字段。
這樣日后更新 msw 包的時(shí)候,public/
目錄下的 worker 腳本會自動更新。
配置 worker
接下來在創(chuàng)建 src/mocks/browser.js
文件:
這一步將我們定義的 handlers 綁定到 mws 上(這時(shí)候定義的 Mock API 才與 mws 有了聯(lián)系)。
我們導(dǎo)出 worker
實(shí)例。
啟動 worker
worker
實(shí)例準(zhǔn)備好后,就要在合適的時(shí)機(jī)啟動 worker 了(worker.start()
):
對 Next.js 項(xiàng)目而言,我們在 pages/_app.tsx
中引入:
我們只在開發(fā)環(huán)境下才進(jìn)行 API Mock?,F(xiàn)在,localhost:3000 打開網(wǎng)頁,看見下面的打印結(jié)果就說明接入成功了。

然后添加按鈕,模擬登錄:
發(fā)現(xiàn)接口 Mock 成功了!

Node 端
配置服務(wù)器
創(chuàng)建src/mocks/server.js文件:
setupServer()
使用之前定義好的 handlers
創(chuàng)建一個(gè)服務(wù)器。
需要注意的是,非 DOM 環(huán)境下的請求 URL 都必須使用絕對地址(absolute request URLs)。
在我們創(chuàng)建的 Next.js 項(xiàng)目中,默認(rèn)會有一個(gè)src/pages/api/hello.ts的 API 路由。我們可以利用它來作為我們測試后端接口請求的方式:
或者借助 axios:
注意,不要使用 Fetch API!mwsjs 是通過攔截 Node 的 http
/https
module 實(shí)現(xiàn) API Mocking 的,因此 Node 中原生支持的 fetch API 會 Mock 失敗的。
啟動服務(wù)器
在pages/_app.tsx中引入:
瀏覽器訪問 http://localhost:3000/api/hello 就能看到正確的 Mock 數(shù)據(jù)了。

區(qū)分 dev/prod 環(huán)境
目前我們的代碼在開發(fā)(development,對應(yīng)next dev)和生產(chǎn)環(huán)境(production,對應(yīng)next start)都會啟用 API Mocking,這不是我們想要的。
因此,我們需要控制只在開發(fā)環(huán)境進(jìn)行 API Mocking,我們可以借助Next.js 的環(huán)境文件支持。
首先,在項(xiàng)目根目錄下創(chuàng)建兩個(gè)文件:.env.development和.env.production:
Next.js 會將 NEXT_PUBLIC_
做前綴的環(huán)境變量,在瀏覽器和 Node 環(huán)境中都設(shè)置。如上所示,開發(fā)環(huán)境我們啟用 mwsjs,生產(chǎn)環(huán)境則禁用 mwsjs。
接下來調(diào)整一下 pages/_app.tsx
中的代碼,判斷僅在 API Mocking 啟用的情況下,引入 mwsjs 配置。
當(dāng)然,如果感覺 _app.tsx
中的代碼很多,也可以將 initMocks
函數(shù)放到 mocks/index.js
文件中:
然后修改 pages/_app.tsx
文件:
還是一樣的效果。
好了,關(guān)于 mwsjs 的介紹就到這里啦,感謝各位的閱讀!
參考鏈接
https://mswjs.io/docs/getting-started/install
https://www.geeksforgeeks.org/node-js-https-request-function/
https://github.com/vercel/next.js/blob/canary/examples/with-msw
https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables