在使用 webpack-dev-server 时,我们可以在 devServer.beforedevServer.after 中添加简易的逻辑来 mock get/post 请求。

先整理下,要达到这些要求,

  • 接口模拟文件放到 mock 目录,文件格式用 js。
  • 我们要 mock get/post 请求,需要支持解析查询参数、body。
  • 更改mock文件时,立即生效,不用重启 wds。

那我们先来捋一捋这个逻辑,当访问一个被mock的get/post请求时,

  1. 针对post请求需要解析body数据,https://www.yuque.com/gdnnth/node/ttcrh9
  2. 读取mock目录下所有的js文件,并把所有mock合并起到mocks集合里
  3. 如果mocks里否含有匹配的路径,返回模拟的结果

话不多说,动手。

1 添加 mock 配置

1.1 写 mock 的基础代码

新建1个文件 addMocks.js,用来写 mock 的逻辑,

  1. const path = require('path')
  2. const fse = require('fs-extra')
  3. const chalk = require('chalk')
  4. /**
  5. * 添加mock支持。
  6. *
  7. * @param {Object} app express服务实例
  8. */
  9. module.exports = function addMocks(app) {
  10. // 第一步,使用body-parser来parse body数据
  11. // parse application/x-www-form-urlencoded
  12. // parse application/json
  13. const bodyParser = require('body-parser')
  14. app.use(bodyParser.urlencoded({ extended: true }))
  15. app.use(bodyParser.json())
  16. app.use(async function(req, res, next) {
  17. // 第二部,去除mocks集合
  18. const mocks = getMocks()
  19. // 第三部,mocks集合中如果有匹配的路径,有则返回模拟结果,否则直接next结束
  20. const mock = mocks[req.path]
  21. if (!mock) {
  22. return next()
  23. }
  24. const { method, result } = mock
  25. if (req.method.toLocaleLowerCase() !== method.toLocaleLowerCase()) {
  26. return next()
  27. }
  28. const _method = chalk.white.bgMagentaBright(` ${req.method} `)
  29. const _mockIndex = chalk.white.bgMagentaBright(' MOCK ')
  30. console.log(`${_method} ${_mockIndex} ${req.url}`)
  31. typeof result === 'function'
  32. ? res.json(await result(req, res, next))
  33. : res.json(result)
  34. })
  35. }
  36. /**
  37. * mock目录下所有的js文件,把他们全部合并到mocks对象,然后返回mocks
  38. * @returns {Object} 接口模拟对象集合
  39. */
  40. function getMocks() {
  41. let mocks = {}
  42. const dir = path.resolve(__dirname, 'mock')
  43. fse.ensureDirSync(dir)
  44. const files = fse.readdirSync(dir)
  45. for (const file of files) {
  46. const filePath = `${dir}/${file}`
  47. if (/\.js$/.test(file) && fse.statSync(filePath).isFile()) {
  48. // 删除了缓存,修改接口问件时,不需要重启
  49. delete require.cache[require.resolve(filePath)]
  50. mocks = { ...mocks, ...require(filePath) }
  51. }
  52. }
  53. return mocks
  54. }

1.2 添加到 wds 配置中

写好 mock 代码后,把它添加到 wds 配置里。
更详细的 wds 配置文档请阅读 https://webpack.docschina.org/configuration/dev-server/

这里需要将 addMocks 放到 devServer.after 里,原因请阅读 body-parser造成DevServer无法转发post请求

  1. // webpack.conf.js
  2. const chalk = require('chalk')
  3. const addMocks = require('./addMocks')
  4. {
  5. devServer: {
  6. port: 3000,
  7. open: true,
  8. overlay: {
  9. warnings: false,
  10. errors: true
  11. },
  12. after(app) {
  13. app.use((req, res, next) => {
  14. // 控制台展示请求
  15. const method = chalk.bgGreen(` ${chalk.black(req.method)} `)
  16. console.log(`${method} ${req.url}`)
  17. next()
  18. })
  19. addMocks(app)
  20. }
  21. }
  22. }

2 来写1个接口mock文件

这是一个示例文件 account.js,

  1. module.exports = {
  2. '/account/get': {
  3. method: 'get',
  4. // json对象
  5. result: {
  6. success: true,
  7. data: { name: 'hello' }
  8. }
  9. },
  10. '/account/get': {
  11. method: 'get',
  12. // pure function
  13. result(req, res, next) {
  14. return {
  15. success: true,
  16. data: {}
  17. }
  18. }
  19. },
  20. '/account/update': {
  21. method: 'post',
  22. // 异步
  23. async result(req, res, next) {
  24. return {
  25. success: true,
  26. data: {}
  27. }
  28. }
  29. },
  30. }

3 在前端代码中使用mock

看看下面这串代码,没有啥改变,原来怎么写的,现在也怎么写就行了。

  1. import axios from 'axios'
  2. const getAccount = async () => {
  3. const data = await axios({
  4. url: '/content/channel/list',
  5. method: 'get',
  6. params
  7. })
  8. // TODO ...
  9. }