在使用 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/jsonconst 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 } = mockif (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.jsconst 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 functionresult(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 ...}
