使用 koa 搭建简易 mock server

目前项目组里的项目,要么没有 mock,要么 mock 数据的方式就是将假数据写到业务代码中,不方便开发。近来刚好有时间,因此抽空对原项目进行一些改造,让其支持数据的 mock。

思路

开发时,我们通过 devServer 代理到测试环境,测试环境返回对应的测试数据,在 mock 时,我们就需要将接口代理到我们自己的 mock 服务器,那么返回的数据就可以自行定义,本文以 webpack 为例,其他的构建工具大致上思路是一样的。

实现

scripts

首先我们要区分开普通的开发模式与 mock 的开发模式,因此在 package.json 中添加一些 script

{
	// ...
  scripts: {
    "dev": "run some script for develop",
    "mock-server": "nodemon mock/index.js",
    "dev:mock": "cross-env MOCK=1 run some script for develop",
    "mock": "npm-run-all -p -r mock-server dev:mock"
  }
}

mock-server 命令用于启动一个 mock 服务, 启动的脚本在 mock/index.js (后面将补充详细的说明)

dev:mock命令与普通开发模式 dev 的区别在于注入一个 MOCK=1, 这个 变量的作用是配置 webpack 的 devServer 中的 proxy,当 process.env.MOCK === '1' 时,将接口代理到 mock server。

mock 命令就是通过 npm-run-allmock-serverdev:mock命令串行执行。

dev:mock

在 dev 模式的配置文件里(如 webpack.dev.conf.js ),修改 devServer.proxy

{
	// ...
  devServer: {
    // ...
    proxy: {
      '/api': {
        // 假设我们的 mocker server 端口在 8009
        process.env.MOCK === '1' ? 'http://localhost:8009' : 'http://your-test-domain',
        changeOrigin: true,
      }
    }
  }
}

这样我们在 mock 的时候,以 /api 开头的接口就能转发到 http://localhost:8009 了,下面让我们完成 mock server 的部分

mock-server

我们创建一个 mock 目录,在下面创建一个 index.js 文件作为启动脚本。

当我们在 mock 目录下新建 *.mock.js, 如 test.mock.js

module.exports = {
  'get /api/test': ctx => {
    ctx.body = {
      code: 0,
      message: "my mock data"
    }
  },
  'post /api/test2': {
      code: 0,
      message: "my mock data2"
   }
};

上面的配置可以看出其实和写 koa 的接口是一样的,为了方便起见,我们还支持直接返回一个对象。

mock/index 的具体实现如下:

const Koa = require('koa');
const app = new Koa();
const glob = require('glob');
const Router = require('koa-router');
const chalk = require('chalk');
const proxy = require('koa-proxies');
const router = new Router();

glob.sync('**/*.mock.js', {
    cwd: __dirname,
    ignore: ['index.js'],
}).forEach(file => {
  // 读取所有 *.mock.js 文件
  const apis = require(`./${file}`);
  // 注册路由
  Object.keys(apis).forEach(api => {
    const [method, url] = api.split(/\s+/);
    router[method](
      url,
      // 如果是方法,则执行方法,否则直接返回对象
      typeof apis[api] === 'function'
      ? apis[api]
      : ctx => {
        ctx.body = apis[api];
      },
    );
  });
});

app.use(async (ctx, next) => {
  await next();
  // 打个日志
  console.log(`${chalk.blue('mock 请求:')} ${ctx.method} ${ctx.url}`);
})
	// 注册路由
  .use(router.routes())
  .use(router.allowedMethods());
	// bypass,如果没有对应的 mock api 的话就还是转发到测试环境
  .use(
    // 代理
    proxy(`/api`, {
      target: 'http://your-test-domain',
      changeOrigin: true,
    }),
  )
	// 监听 8090 端口
  .listen(8009, () => {
	  console.log(chalk.green('mock server is running at port 8009'));
	});

至此, 通过 koa 完成了一个很简单的 mock 服务。