🇨🇳 中文版说明 → README.zh-CN.md
Recommend: use version@
v1.0.0
+
Make a easy mock-server to mock api, with GET /a/b/c
→ ./mocks/data/GET/a/b/c.json
mapping
- ✔️ Zero intrusion into front-end code
- ✔️ Support https protocol
- ✔️ Support all methods, like
GET
,POST
,PUT
,DELETE
etc. - ✔️ Support mock data file type:
json
|json5
- ✔️ Support custom your middleware in
middleware.{js|cjs|ts}
, write askoa2 middleware
(orexpress-middleware
both ok withfunc.isExpress=true
) - ✔️ Support custom special routes mapping in
routes.json
, mapping multiple request to same resolve file。 routes key alignglob
expression - ✔️ Support mock logic file type:
js
|cjs
|ts
- ✔️ Slightly support for
socket
simulations - ✔️ Support the generation of some simple simulation data, in
mihawk/tools
, eg:createRandPhone
、createRandEmail
npm i -g mihawk
mihawk --port=8888
# mihawk -p 8888
then open browser and visit
http://localhost:8888
mock data directory:
./mocks/data
./mocks
│
├── /data
│ │
│ ├── DELETE
│ │ ├──/*.js DELETE request resolve logic
│ │ └──/*.json DELETE request resolve data
│ │
│ ├── GET
│ │ ├──/*.js GET request resolve logic
│ │ └──/*.json GET request resolve data
│ │
│ ├── POST
│ │ ├──/*.js POST request resolve logic
│ │ └──/*.json POST request resolve data
│ │
│ └── PUT
│ ├──/*.js PUT request resolve logic
│ └──/*.json PUt request resolve data
│
├── middleware.js [optional] resolve middleware
│
└── routes.json [optional] common routes
mapping:
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
: mock request urlJSON-file
: mock origin datamock-file
: resolve mock logic, base on origin data
Finally, the return data will be the data after processing mock-file (the mock-file
) with origin data (the JSON-file
)
A more recommended way to use it is to write all config props into the
.mihawkrc.json
in the root directoryAnd then run
mihawk
in you shell
mihawk init
then edit the
.mihawkrc.json
to customize your config
{
"host": "0.0.0.0",
"port": 8888,
"https": false,
"cors": true,
"cache": true,
"watch": true,
"mockDir": "mocks",
"mockDataFileType": "json",
"mockLogicFileType": "none"
}
About root config props:
host
: string, default0.0.0.0
, server listen on this hostport
: number, default8888
, server listen on this porthttps
: boolean, defaultfalse
, iftrue
, will use https protocolcors
: boolean, defaulttrue
, iftrue
, will addAccess-Control-Allow-Origin: *
(and other necessary cors props in headers ) to the response headerscache
: boolean, defaulttrue
, iftrue
, will cache the mock data and return the cached data when the request is the samewatch
: boolean, defaulttrue
, iftrue
, will watch the mock data directory and reload when changedmockDir
: string, defaultmocks
, the directory of mock datamockDataFileType
: stringjson
|json5
, defaultjson
, the file type of mock datamockLogicFileType
: stringjs
|cjs
|ts
|none
, defaultnone
, the file type of mock logicsetJsonByRemote
: { enable: boolean; target: string; timeout?: number; rewrite?: (path: string) => string } | null- Default:
undefined
- When local mock file not found:
- If set to proxy object with
{enable:true, target:'xxx' }
to fetch from remote proxy - If set to
null
/undefined
to disable
- If set to proxy object with
- Proxy config requires:
target
(required): remote server URL, requiredrewrite
: optional path rewrite functiontimeout
: request timeout in milliseconds
- Default:
More detail → src/com-types.ts, interface MihawkRC define the config props
graph LR
A[Dev Mode: Request] --> B(devServer)
B --> D1[Mode 1: mockServer → Local launched mockServer]
B --> D2[Mode 2: Proxy to backend → Change proxy to backend's address]
D1 --> C(Mihawk)
D2 --> E(BackendServer)
F[Production Mode: Request] --> G(BackendServer)
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
In the above diagram,
devServer
is typically provided by bundling tools during local development, such as Vite or Webpack, which have corresponding configuration options.
Essentially, it is based on the proxy functionality of
devServer
, forwarding requests to the mihawk server.
in vite.config.js
file:
import { defineConfig } from 'vite';
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8888', // mihawk server address
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
},
},
},
});
in webpack.config.js
file:
// webpack.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8888', // mihawk server address
changeOrigin: true,
pathRewrite: { '^/api': '' },
},
},
},
};
For request GET /api/fetch_a_random_number
,it return response with random number data
{
"code": 200,
"data": 123456,
"msg": "success"
}
You cal aslo dont do this step, coz the mock data file is auto create when request a not exists file
Now, if request GET /api/fetch_a_random_number
,return data is 123456
, it is fixed data
module.exports = async function (oldJson) {
oldJson.data = Math.floor(Math.random() * 1000000); // generate random number
return oldJson; // return data, it is required
};
Start mihawk
server now, if request GET /api/fetch_a_random_number
,return data is random number, each request return a different data
About MockLogic File:
- Both support
js
|cjs
|ts
, the process is same。Attention toexport default
is necessary ints
file!- Recommend to set
autoCreateMockLogicFile
totrue
in.mihawkrc.json
, then, if request a not exists mock data file, it will auto create a mock logic file for you- Of course, it is worth mentioning that MockLogic files aren't necessary files. If there is no logical demand for data processing, using only JSON files can also simulate the request
/**
* mihawk's routes file:
*/
const routes: Record<string, string> = {
'GET /test': './GET/test',
'GET /test-*': './GET/test', // key: routePath,support glob expression; value: mock data file path (no ext)
};
//
export default routes;
/**
* 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';
/**
* Middleware functions, to implement some special data deal logic,
* - This function exec before the default-mock-logic. Simply return or don`t call "await next()" could skip default-mock-logic
* - This function is a standard KOA middleware that follows the KOA onion ring model
* - see more:https://koajs.com/#middleware
* @param {Context} ctx
* @param {Next} next
* @returns {Promise<void>}
*/
export default async function middleware(ctx: KoaContext, next: KoaNext) {
// do something here
console.log(ctx.url);
if (ctx.peth === '/diy') {
ctx.body = 'it is my diy logic';
} else {
await next(); // default logic (such like mock json logic)
}
}
Set
middleware.isExpress=true
to explicit definition a express middleware function before export, if you write in express-stype Other complex diy middleware demo, base on koa-router & koa-compose, middleware.md
'use strict;';
/**
* GET /xxx
* This file isn‘t mandatory. If it is not needed (such as when there is no need to modify response data), it can be deleted directly
*/
/**
* Mock data resolve function, the original data source is the JSON file with the same name as this file
* @param {object} originData (mocks/data/GET/xxx.json)
* @param {MhkCvtrExtra} extra { url,method,path,query,body }
* @returns {object} newData
*/
export default async function convertData(originData: Record<string, any>, extra: Record<string, any>) {
// write your logic here...
originData.newProp = 'newPropXxx';
return originData; // return data, it is required
}
- Mockjs is a front-end mockjs library that provides powerful simulated data generation capabilities
- Mihawk is a Node.js mock service that can be used with front-end projects or standalone; it provides mock capabilities for httpServer/SocketServer based on Nodejs
- Mockjs intercepts requests and returns simulated data by hijacking xhr/fetch, etc., which requires certain modifications to front-end engineering code, and there are some differences in the request sending/receiving process compared to the real online environment
- Mihawk intercepts requests and returns simulated data through Koa2 middleware format, without requiring any modifications to front-end engineering code, and the request sending/receiving process is identical to the real online environment
- Mockjs is used for simulated data production, generating corresponding fake data through its specific syntax
- Mihawk is used to simulate BackendServer based on Nodejs, such as Socket, httpServer, etc., combined with simple data generation functions to complete fake data generation
mhiawk/tools
: Built-in utility functions likecreatRandXxx
for generating fake data; this functionality is not as powerful as Mockjs- Consider using both mockjs's
data generate
and mihawk'sserver mock
together; they are not mutually exclusive
- Consider using both mockjs's
your_project/mocks/middleware.ts
: Simulate backend services, such as httpServeryour_project/mocks/socket.ts
: Simulate backend services, such as socketServer