在開發基於api互動、前後端分離的網頁應用時,經常會遇到幾個問題:
- 前端頁面已經編排好了,但是後臺介面還沒準備好,或者是突然出現Bug,這樣沒辦法進行對接測試。
- 我們希望伺服器返回特定型別的資料,以測試某頁面在特定條件下是否存在問題,但作為前端我們一般不會接觸到後端程式碼和資料庫,每次都找後端新增模擬資料又很麻煩。
為解決這兩個問題,最簡單的解決辦法就是搭建一個mock server,專門返回需要的模擬資料。
webpack-dev-server
是我們開發vue、react時必備的工具,通過webpack-dev-server
的before
鉤子,可以在webpack-dev-server
上新增我們需要的mock server功能,而不需要另行搭建伺服器。
在一通搜尋後,我找到了這篇文章和這個webpack中介軟體webpack-api-mocker,只需要少許修改就能webpack-dev-server
當做mock server來用,並且對同一URL下的GET
、POST
、PATCH
等不同的HTTP METHOD
做分別處理,支援熱切換。
使用方法很簡單,在webpack.dev.conf.js
的devServer
中新增新鉤子before
,將所有請求交由apiMocker
處理,然後當需要使用模擬資料時,只需要將請求的URL改為webpack伺服器上既可。
npm install webpack-api-mocker --save-dev
複製程式碼
const apiMocker = require(`webpack-api-mocker`)
config = {
...
devServer: {
before(app) {
apiMocker(app, path.resolve(`mock/api.js`))
}
}
...
}
複製程式碼
api.js
const fs = require(`fs`);
function fromJSONFile(filename) {
return (req, res) => {
const data = fs.readFileSync(`mock/data/${filename}.json`).toString();
const json = JSON.parse(data);
return res.json(json);
};
}
const proxy = {
`GET /app/user/profile`: fromJSONFile(`profile`),
};
module.exports = proxy;
複製程式碼
修改URL
axios.get(`user/info`).then(...)
// 修改URL,加上字首
axios.get(`http://127.0.0.1:8080/` + `user/info`).then(...)
複製程式碼
更進一步
經過上面的步驟,mock server已經基本能執行了,但還是有一些不友好。每次需要使用模擬資料時,都要修改專案原始碼,改寫請求的URL,在測試完畢後還得再改回來,如果該請求在原始碼內有多處地方使用,那改動的地方就多了,比較麻煩。我們可以再進行一些改進。
改進的思路就是開啟mock server後,將所有對api伺服器的請求都傳送到webpack server
上,webpack server
攔截並處理所有已定義有模擬資料的介面請求,而未定義的介面請求則轉發到api伺服器上。
上面說的那個專案作者已經合併了我的PR,下面這段可以不用理了,繼續用上面那個webpack-api-mocker
首先,我們要對前面用到的那個中介軟體webpack-api-mocker進行改進,修改後的程式碼在我的github上,外掛主要就一個檔案
index.js
,複製下來直接使用即可。修改了那些內容可以看commit log
然後新增一個新的npm命令dev-mock
,定義一個環境變數MOCK
來控制是否開啟mock server
:
"script": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+ "dev-mock": "MOCK=true webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
}
複製程式碼
webpack config中當MOCK
變數存在時才開啟mock server
config = {
...
devServer: {
if (process.env.MOCK) {
before(app) {
apiMocker(app, path.resolve(`mock/api.js`), {
proxy: {
`/app//*`: `http://api.leaderlegend.com`,
}
});
}
}
}
...
}
複製程式碼
為了在程式碼中使用環境變數MOCK
,我們要在webpack config內傳遞該值。如何傳值參考StackOverflow上的這個回答Passing environment-dependent variables in webpack
。
config = {
...
devServer: ...
plugins: [
new webpack.DefinePlugin({
`process.env`: {
NODE_ENV: process.env.NODE_ENV,
MOCK: process.env.MOCK,
}
}),
...
]
...
}
複製程式碼
通過判斷環境變數MOCK
來確定api伺服器地址,這裡最好保持第一個path相同以更方便轉發
const BASE_URL = process.env.MOCK ? `http://127.0.0.1:8080/app/` : `http://api.harlanluo.com/app/`;
複製程式碼
到此為止已經全部完成,需要使用模擬資料時,使用npm run dev-mock
命令來執行,,不需要時則使用npm run dev
,無需對專案原始碼對做任何修改。