UNPKG

mihawk

Version:

A tiny & simple mock server tool, support json,js,cjs,ts(typescript).

331 lines (264 loc) 13 kB
# Mihawk (简单小巧的 MockServer 工具) [![version](https://img.shields.io/npm/v/mihawk.svg 'version')](https://www.npmjs.com/package/mihawk) [![download](https://img.shields.io/npm/dt/mihawk.svg 'download')](https://www.npmjs.com/package/mihawk) [![GitHub issues](https://img.shields.io/github/issues/Froguard/mihawk.svg)](https://github.com/Froguard/mihawk/issues?q=is%3Aopen+is%3Aissue) [![Github licences](https://img.shields.io/github/license/Froguard/mihawk.svg)](https://github.com/Froguard/mihawk/blob/master/LICENSE) <!-- [![nodei](https://nodei.co/npm/mihawk.png?downloads=true)](https://www.npmjs.com/package/mihawk) --> > 🇺🇸 English → [README.md](https://github.com/Froguard/mihawk/blob/master/README.md) > 推荐使用版本 `v1.0.0`+ 采用 `GET /a/b/c``./mocks/data/GET/a/b/c.json` 方式去做 api 请求的 mock server 工具 - ✅ 对于项目的前端代码零侵入 - ✅ 支持 https 协议 - ✅ 支持所有有请求方法,例如 `GET`, `POST`, `PUT`, `DELETE` 等,通过文件路径方式自动映射请求路径 - ✅ 用以定义 mock 的数据文件,同时支持 `json` | `json5` 两种格式 - ✅ 用以处理 mock 数据的逻辑文件,支持 `js` | `cjs` | `ts` 三种格式,可以对 json 请求进行二次修改,以便于支持一些动态逻辑处理 - ✅ 在默认的文件映射功能之外,允许在 `middleware.{js|cjs|ts}` 文件中,通过暴露 koa2 middleware 函数的形式,完成自定义路由的复杂的处理逻辑 (express中间件也兼容,通过设置中间件函数func.isExpress=trye即可) - ✅ 允许自定义 `routes.json` 文件方式, 让多条路径映射到同一个文件,其中 key 允许 glob 表达式 - ✅ 简单支持 `socket` 的模拟 - ✅ 通过 `mihawk/tools` 提供一些简单的函数,便于模拟数据的生成,如: `createRandPhone``createRandEmail` ## 安装 ```sh npm i -g mihawk ``` ## 使用 ```sh mihawk --port=8888 # mihawk -p 8888 ``` > 打开网页 `http://localhost:8888` > > mock 文件夹: `./mocks/data` ```sh ./mocks │ ├── /data │ │ │ ├── DELETE │ │ ├──/*.js DELETE 请求处理逻辑 │ │ └──/*.json DELETE 请求对应的数据 │ │ │ ├── GET │ │ ├──/*.js GET 请求处理逻辑 │ │ └──/*.json GET 请求对应的数据 │ │ │ ├── POST │ │ ├──/*.js POST 请求处理逻辑 │ │ └──/*.json POST 请求对应的数据 │ │ │ └── PUT │ ├──/*.js PUT 请求处理逻辑 │ └──/*.json PUt 请求对应的数据 │ ├── middleware.js [optional] 自定义koa2中间件,用以实现自定义逻辑 │ └── routes.json [optional] 全局路由映射,用以进行路由逻辑复用(将多个路由通过glob表达式映射到相同文件) ``` > 路由与文件的映射关系 ```sh request : GET http://localhost:8888/a/b/c/d JSON-file : data/get/a/b/c/d.json mock-file : data/get/a/b/c/d.js ``` - `request`: 模拟的请求路径 - `JSON-file`: mock 用的原始 json 数据 - `mock-file`: mock 的处理逻辑文件,可以修改 json 数据,例如添加一些自定义的属性等 最终请求的返回结果,将会是经由 mock-file 处理 JSON-file 后的数据 ## 推荐用法 > 比较推荐的办法是,通过在根目录下,自定义一个 `.mihawkrc.json` 文件,用来完成配置项的编写 > > 然后运行 `mihawk` 命令 ### 初始化 `.mihawkrc.json` ```sh mihawk init ``` > 然后编辑该文件,完成配置 ```json { "host": "0.0.0.0", "port": 8888, "https": false, "cors": true, "cache": true, "watch": true, "mockDir": "mocks", "mockDataFileType": "json", "mockLogicFileType": "none" } ``` 关于这里边的配置项: - `host`: string,默认值为 `0.0.0.0`,server 将监听该地址 - `port`: number, 默认值为 `8888`,server 将监听该端口 - `https`: boolean, 默认值为 `false`,如果为 `true`,则使用 https 协议 - `cors`: boolean, 默认值为 `true`,如果为 `true`,则添加 `Access-Control-Allow-Origin: *` 等等跨域相关的到响应头 - `cache`: boolean, 默认值为 `true`,如果为 `true`,则对返回的 json 数据进行缓存,下次请求相同路径时,直接返回缓存的数据 - `watch`: boolean, 默认值为 `true`,如果为 `true`,则对 mock 数据目录进行监听,文件变动时,自动重新加载。(优先级大于缓存,当检测到文件变更,会强制刷新当前缓存) - `mockDir`: string, 默认值为 `mocks`,表示 mock 数据的目录 - `mockDataFileType`: string 可选值为 `json` | `json5` 之一, 默认值为 `json`,表示 mock 数据的文件格式 - `mockLogicFileType`: string 可选值为 `js` | `cjs` | `ts` | `none` 之一, 默认值为 `none`,表示 mock 数据的处理逻辑文件 - `setJsonByRemote`: { enable: boolean; target: string; timeout?: number; rewrite?: (path: string) => string } | null - 默认值: `undefined` - 当本地 mock 文件不存在时: 1. 设置为包含 `{enable:true, target:'xxx' }` 的代理对象时,将从远程代理获取数据 2. 设置为 `null`/`undefined` 时禁用该功能 - 代理配置要求: - `target`(必填): 远端服务器URL,该值为必须值 - `rewrite`: 可选路径重写函数 - `timeout`: 请求超时时间(毫秒) > 更多说明,详见 ts 定义文件 → [src/com-types.ts](https://github.com/Froguard/mihawk/blob/master/src/com-types.ts), interface MihawkRC 定义了所有配置项 ## 在常见的打包工具中,配置 Mihawk ```mermaid graph LR A[开发模式: 请求] --> B(devServer) B --> D1[Mode 1: mockServer → 本地Mock服务器] B --> D2[Mode 2: 代理至后端 → 某个后端服务地址] D1 --> C(Mihawk) D2 --> E(后端服务) F[生产环境: 请求] --> G(后端服务) style A fill:#2c2c2c,stroke:#ccc,fill-opacity:1,color:#eee style B fill:#5e6472,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 style C fill:#09c,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 style D1 fill:#5e6472,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 style D2 fill:#5e6472,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 style E fill:#7a6da2,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 style F fill:#2c2c2c,stroke:#ccc,fill-opacity:1,color:#eee style G fill:#7a6da2,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0 classDef devStyle fill:#2c2c2c,stroke:#ccc,fill-opacity:1,color:#eee; classDef serviceStyle fill:#5e6472,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0; classDef backendStyle fill:#7a6da2,stroke:#f0f0f0,fill-opacity:1,color:#f0f0f0; class A,F devStyle class B,D1,D2 serviceStyle class C,E,G backendStyle ``` > 上图中 `devServer` 一般为本地开发时候的打包工具可提供,如 vite,webpack 等,均有对应配置 > 本质上就是基于 `devServer` 的代理功能,将请求转发至 `mihawk` 服务器 ### vite 配置 `vite.config.js` 文件: ```js import { defineConfig } from 'vite'; export default defineConfig({ server: { proxy: { '/api': { target: 'http://localhost:8888', // mihawk server address changeOrigin: true, rewrite: path => path.replace(/^\/api/, ''), }, }, }, }); ``` ### webpack 配置 `webpack.config.js` 文件: ```js // webpack.config.js module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8888', // mihawk server address changeOrigin: true, pathRewrite: { '^/api': '' }, }, }, }, }; ``` ## 示例 假设有一个请求 `GET /api/fetch_a_random_number`,返回一个随机数,那么可以这样写: ### 1.创建一个 `mocks/data/GET/api/fetch_a_random_number.json` 文件,内容如下 ```json { "code": 200, "data": 123456, "msg": "success" } ``` > 注意,这一步也可以不通过手动创建,当请求发过来的时候,如果文件不存在,会自动创建一个空的 json 文件,并返回给客户端,然后在这个自动创建的文件里修改即可 此时,如果请求 `GET /api/fetch_a_random_number`,返回的数据就是这个文件里的内容,即:会得到固定的 `123456` 这个数据 ### 2.创建一个 `mocks/data/GET/api/fetch_a_random_number.js` 文件,内容如下 ```js module.exports = async function (oldJson) { oldJson.data = Math.floor(Math.random() * 1000000); // 随机生成一个 6 位的数字 return oldJson; // 必要的返回 }; ``` 完成文件创建,启动 `mihawk` 服务,此时,如果请求 `GET /api/fetch_a_random_number`,返回的数据是随机的,即:每次请求,返回的数据都不一样 > 其他说明: > > - 关于 MockLogic 文件,除了支持 js(cjs相同) 外,还支持 `ts`, 创建 `ts` 文件一样的效果,这里不在赘述,唯一需要注意的是,需要在 ts 文件中进行 `export default` 操作 > - 推荐可以在 `.mihawkrc.json` 中,配置 `autoCreateMockLogicFile` 为 `true`,这样,当请求一个不存在的 mock 数据文件时,会自动创建一个对应的 mock logic 文件,方便后续开发 > - 当然,值得一提的时,**MockLogic 文件,并非必** 要文件,如果没有数据的处理逻辑诉求,**只使用 json 文件也是可以的** ## Mock 文件示例 ### `routes` 文件 ts ```ts /** * mihawk's routes file: */ const routes: Record<string, string> = { 'GET /test': './GET/test', 'GET /test-*': './GET/test', // key 为路由,支持 glob 表达式,value 为处理文件的路径(不加后缀) }; // export default routes; ``` ### `middleware` 文件 ts 示例 ```ts /** * mihawk's middleware file: * - just a Koa2 Middleware */ import type { Context: KoaContext, Next: KoaNext } from 'koa'; // need koa@v2.0.0+ (eg: koa@^2.15.3) // import type { KoaContext, KoaNext } from 'mihawk/con-types'; /** * koa 中间件函数 * - 标准的 koa2 中间件函数写法,遵循 koa 的洋葱圈模型 * - 注意:如果想要跳过内置的 mock 逻辑,如无需走 json mock 那一套,直接 return,或者不调用 await next() 语句接口 * - 更多文档:https://koajs.com/#middleware * @param {Context} ctx * @param {Next} next * @returns {Promise<void>} */ export default async function middleware(ctx: KoaContext, next: KoaNext) { console.log(ctx.url); if (ctx.peth === '/diy') { ctx.body = 'it is my diy logic'; } else { await next(); // 默认的 json mock 逻辑,如果不需要,则不调用即可 } } ``` > 如果使用的是 express 风格的 中间件函数,需要给函数设置 `isExpress=true` 标明其是一个 express 中间件 > 其他一些稍微复杂点的 middleware demo,比如基于 koa-router 和 koa-compose, 详见 [middleware.md](./docs/middleware.md) ### `mock-logic` 文件 ts 示例 ```ts 'use strict;'; /** * GET /xxx * */ /** * json 数据二次处理函数 * @param {object} originData (mocks/data/GET/xxx.json) * @param {MhkCvtrExtra} extra { url,method,path,query,body }, 请求相关的基本信息字段 * @returns {object} newData 处理后的新数据(需要显式进行 return) */ export default async function convertData(originData: Record<string, any>, extra: Record<string, any>) { // 自定义处理逻辑 originData.newProp = 'newPropXxx'; return originData; // 需要进行显式 return } ``` ## 和 Mockjs 区别? ### 1、定位不同 - Mockjs 是一个前端的 mockjs 库,提供了强大的模拟数据生成功能 - Mihawk 是一个 Node.js 的 mock 服务,可以和前端项目一起使用,也可以单独使用;提供了基于 Nodejs 的 httpServer|SocketServer 的 mock 能力 ### 2、实现方式不同 - Mockjs 通过劫持 xhr/fetch 等,对于请求进行拦截并返回模拟数据,对于前端工程代码有一定改造,且请求与真实线上环境的收发过程有一定差异 - Mihawk 通过 Koa2 中间件的形式,对请求进行拦截并返回模拟数据,对于前端工程代码无改造,且请求与真实线上环境的收发过程无差异 ### 3、常用使用场景 - Mockjs 用于模拟数据的生产,通过其提供的特定语法,生成对应的假数据 - Mihawk 用于基于 Nodejs 实现对于 BackendSenver 的模拟,比如 Socket, httpServer 等,搭配简单的数据生产函数,完成假数据的生成 - `mhiawk/tools`: 内置的一些工具函数 `creatRandXxx` 等生成假数据,这部分功能并没有 Mockjs 那么强大; - 可以考虑同时使用 mockjs 的 `data generate` 和 mihawk 的 `server mock`,配合完成;两者并不冲突 - `mocks/middleware.ts`: 模拟后端服务,比如 httpServer - `mocks/socket.ts`: 模拟后端服务,比如 socketServer