在使用 webpack-dev-server 时,我们可以在 devServer.before 或 devServer.after 中添加简易的逻辑来 mock get/post 请求。
先整理下,要达到这些要求,
- 接口模拟文件放到 mock 目录,文件格式用 js。
- 我们要 mock get/post 请求,需要支持解析查询参数、body。
- 更改mock文件时,立即生效,不用重启 wds。
那我们先来捋一捋这个逻辑,当访问一个被mock的get/post请求时,
- 针对post请求需要解析body数据,https://www.yuque.com/gdnnth/node/ttcrh9
- 读取mock目录下所有的js文件,并把所有mock合并起到mocks集合里
- 如果mocks里否含有匹配的路径,返回模拟的结果
话不多说,动手。
1 添加 mock 配置
1.1 写 mock 的基础代码
新建1个文件 addMocks.js,用来写 mock 的逻辑,
const path = require('path')
const fse = require('fs-extra')
const chalk = require('chalk')
/**
* 添加mock支持。
*
* @param {Object} app express服务实例
*/
module.exports = function addMocks(app) {
// 第一步,使用body-parser来parse body数据
// parse application/x-www-form-urlencoded
// parse application/json
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
app.use(async function(req, res, next) {
// 第二部,去除mocks集合
const mocks = getMocks()
// 第三部,mocks集合中如果有匹配的路径,有则返回模拟结果,否则直接next结束
const mock = mocks[req.path]
if (!mock) {
return next()
}
const { method, result } = mock
if (req.method.toLocaleLowerCase() !== method.toLocaleLowerCase()) {
return next()
}
const _method = chalk.white.bgMagentaBright(` ${req.method} `)
const _mockIndex = chalk.white.bgMagentaBright(' MOCK ')
console.log(`${_method} ${_mockIndex} ${req.url}`)
typeof result === 'function'
? res.json(await result(req, res, next))
: res.json(result)
})
}
/**
* mock目录下所有的js文件,把他们全部合并到mocks对象,然后返回mocks
* @returns {Object} 接口模拟对象集合
*/
function getMocks() {
let mocks = {}
const dir = path.resolve(__dirname, 'mock')
fse.ensureDirSync(dir)
const files = fse.readdirSync(dir)
for (const file of files) {
const filePath = `${dir}/${file}`
if (/\.js$/.test(file) && fse.statSync(filePath).isFile()) {
// 删除了缓存,修改接口问件时,不需要重启
delete require.cache[require.resolve(filePath)]
mocks = { ...mocks, ...require(filePath) }
}
}
return mocks
}
1.2 添加到 wds 配置中
写好 mock 代码后,把它添加到 wds 配置里。
更详细的 wds 配置文档请阅读 https://webpack.docschina.org/configuration/dev-server/。
这里需要将 addMocks 放到 devServer.after 里,原因请阅读 body-parser造成DevServer无法转发post请求。
// webpack.conf.js
const chalk = require('chalk')
const addMocks = require('./addMocks')
{
devServer: {
port: 3000,
open: true,
overlay: {
warnings: false,
errors: true
},
after(app) {
app.use((req, res, next) => {
// 控制台展示请求
const method = chalk.bgGreen(` ${chalk.black(req.method)} `)
console.log(`${method} ${req.url}`)
next()
})
addMocks(app)
}
}
}
2 来写1个接口mock文件
这是一个示例文件 account.js,
module.exports = {
'/account/get': {
method: 'get',
// json对象
result: {
success: true,
data: { name: 'hello' }
}
},
'/account/get': {
method: 'get',
// pure function
result(req, res, next) {
return {
success: true,
data: {}
}
}
},
'/account/update': {
method: 'post',
// 异步
async result(req, res, next) {
return {
success: true,
data: {}
}
}
},
}
3 在前端代码中使用mock
看看下面这串代码,没有啥改变,原来怎么写的,现在也怎么写就行了。
import axios from 'axios'
const getAccount = async () => {
const data = await axios({
url: '/content/channel/list',
method: 'get',
params
})
// TODO ...
}