vite-plugin-mock-dev-server 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh-CN.md DELETED
@@ -1,943 +0,0 @@
1
- # vite-plugin-mock-dev-server
2
-
3
- <br>
4
- <br>
5
- <p align="center">
6
- <b>vite mock开发服务(mock-dev-server)插件。</b>
7
- </p>
8
-
9
- <p align="center">在 vite 开发环境中,注入一个 mock-dev-server。</p>
10
-
11
- <br>
12
- <p align="center">
13
- <a href="https://www.npmjs.com/package/vite-plugin-mock-dev-server"><img alt="npm" src="https://img.shields.io/npm/v/vite-plugin-mock-dev-server?style=flat-square"></a>
14
- <img alt="node-current" src="https://img.shields.io/node/v/vite-plugin-mock-dev-server?style=flat-square">
15
- <img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/vite-plugin-mock-dev-server/peer/vite?style=flat-square">
16
- <img alt="npm" src="https://img.shields.io/npm/dm/vite-plugin-mock-dev-server?style=flat-square">
17
- <br>
18
- <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pengzhanbo/vite-plugin-mock-dev-server/lint.yml?style=flat-square">
19
- <a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fpengzhanbo%2Fvite-plugin-mock-dev-server?ref=badge_shield"><img alt="fossa status" src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fpengzhanbo%2Fvite-plugin-mock-dev-server.svg?type=shield"></a>
20
- </p>
21
- <br>
22
- <p align="center">
23
- <a href="/README.md">English</a> | <span>简体中文</span>
24
- </p>
25
- <br>
26
- <br>
27
-
28
- ## 特性
29
-
30
- - ⚡️ 轻量,灵活,快速
31
- - 🧲 非注入式,对客户端代码无侵入
32
- - 💡 ESModule/commonjs
33
- - 🦾 Typescript
34
- - 🔥 热更新
35
- - 🏷 支持 `json` / `json5` 编写 mock 数据
36
- - 📦 自动加载 mock 文件
37
- - 🎨 可选择你喜欢的任意用于生成mock数据库,如 `mockjs`,或者不使用其他库
38
- - 📥 路径规则匹配,请求参数匹配
39
- - ⚙️ 随意开启或关闭对某个接口的 mock配置
40
- - 📀 支持多种响应体数据类型,包括 `text/json/buffer/stream`.
41
- - ⚖️ 使用 `server.proxy` 配置
42
- - 🍕 支持在 mock文件中使用 `viteConfig.define`配置字段 和 `env` 环境变量
43
- - ⚓️ 支持在 mock文件中使用 `viteConfig.resolve.alias` 路径别名
44
- - 🌈 支持 `vite preview` 模式
45
- - 📤 支持 multipart 类型,模拟文件上传
46
- - 📥 支持模拟文件下载
47
- - ⚜️ 支持模拟 `WebSocket`
48
- - 🗂 支持构建可独立部署的小型mock服务
49
-
50
- ## 文档
51
-
52
- 查看 [Documentation](https://vite-plugin-mock-dev-server.netlify.app/) 了解更多。
53
-
54
- [![Netlify Status](https://api.netlify.com/api/v1/badges/9ccda610-2c6a-4cd0-aeaa-a8932f2b477c/deploy-status)](https://app.netlify.com/sites/vite-plugin-mock-dev-server/deploys)
55
-
56
- ## 使用
57
-
58
- ### 安装
59
-
60
- ```sh
61
- # npm
62
- npm i -D vite-plugin-mock-dev-server
63
- # yarn
64
- yarn add vite-plugin-mock-dev-server
65
- # pnpm
66
- pnpm add -D vite-plugin-mock-dev-server
67
- ```
68
-
69
- ### 配置
70
-
71
- `vite.config.ts`
72
-
73
- ```ts
74
- import { defineConfig } from 'vite'
75
- import mockDevServerPlugin from 'vite-plugin-mock-dev-server'
76
-
77
- export default defineConfig({
78
- plugins: [
79
- mockDevServerPlugin(),
80
- ],
81
- // 这里定义的字段,在mock中也能使用
82
- define: {},
83
- server: {
84
- proxy: {
85
- '^/api': { target: 'http://example.com' }
86
- }
87
- }
88
- })
89
- ```
90
-
91
- 插件会读取 `server.proxy` 或 `options.prefix` 的配置,对匹配的 url 启用mock 匹配。
92
-
93
- 插件也会读取 `define` 配置, 支持在 mock 文件中直接使用。
94
-
95
- > 因为一般场景下,我们只需要对有代理的url进行mock,这样才能通过 vite 提供的 http 服务进行 代理和 mock,
96
- > 但你也可以使用 `options.prefix`配置 mock
97
-
98
- ### 编写mock文件
99
-
100
- 默认配置,在你的项目根目录的 `mock` 目录中编写mock数据:
101
-
102
- `mock/**/*.mock.ts` :
103
-
104
- ```ts
105
- import { defineMock } from 'vite-plugin-mock-dev-server'
106
-
107
- export default defineMock({
108
- url: '/api/test',
109
- body: { a: 1, b: 2 }
110
- })
111
- ```
112
-
113
- ## 方法
114
-
115
- ### mockDevServerPlugin(options)
116
-
117
- vite plugin
118
-
119
- `vite.config.ts`
120
-
121
- ```ts
122
- import { defineConfig } from 'vite'
123
- import mockDevServerPlugin from 'vite-plugin-mock-dev-server'
124
-
125
- export default defineConfig({
126
- plugins: [
127
- mockDevServerPlugin(),
128
- ]
129
- })
130
- ```
131
-
132
- #### options
133
-
134
- - `options.prefix`
135
-
136
- **类型:** `string | string[]`
137
-
138
- 为mock服务器配置自定义匹配规则。任何请求路径以 `prefix` 值开头的请求将被代理到对应的目标。如果 `prefix` 值以 `^` 开头,将被识别为 RegExp。
139
-
140
- > 一般情况下, `server.proxy` 已经足够满足需求,添加此项是为了与某些场景兼容。
141
-
142
- **默认值:** `[]`
143
-
144
- - `options.wsPrefix`
145
-
146
- **类型:** `string | string[]`
147
-
148
- 配置 webSocket 服务 匹配规则。任何请求路径以 `wsPrefix` 值开头的 `ws/wss` 协议请求,将被代理到对应的目标。
149
- 如果`wsPrefix`值以 `^` 开头,将被识别为 RegExp。
150
-
151
- > 与 http mock 默认使用 `viteConfig.server.proxy` 不同的是,`websocket mock` 不会使用 `viteConfig.server.proxy` 中的 ws 相关的配置,且配置在 `wsPrefix` 中的规则,不能同时配置在 `viteConfig.server.proxy`中,因为会导致在 vite 在启动服务时产生冲突,因为不能对同一个请求实现多个的 `WebSocketServer`实例。
152
- > 该冲突既不是 `vite` 的问题,也不是插件的问题,这属于合理的错误类型。在进行 `WebSocket Mock`和 `WebSocket Proxy` 切换时,请注意配置不要出现重复导致冲突。
153
-
154
- - `option.cwd`
155
-
156
- **类型:** `string`
157
-
158
- 配置 `include` 和 `exclude` 的匹配上下文
159
-
160
- **默认值:** `process.cwd()`
161
-
162
- - `option.include`
163
-
164
- **类型:** `string | string[]`
165
-
166
- 配置读取 mock文件,可以是一个 目录,glob,或者一个数组
167
-
168
- **默认值:** `['mock/**/*.mock.{js,ts,cjs,mjs,json,json5}']` (相对于根目录)
169
-
170
- - `options.exclude`
171
-
172
- **类型:** `string | string[]`
173
-
174
- 配置读取 mock文件时,需要排除的文件, 可以是一个 目录、glob、或者一个数组
175
-
176
- **默认值:** `['**/node_modules/**', '**/.vscode/**', '**/.git/**']`
177
-
178
- - `options.reload`
179
-
180
- **Type:** `boolean`
181
-
182
- mock资源热更新时,仅更新了数据内容,但是默认不重新刷新页面。当你希望每次修改mock文件都刷新页面时,可以打开此选项。
183
-
184
- **Default:** `false`
185
-
186
- - `options.cors`
187
-
188
- **Type:** `boolean | CorsOptions`
189
-
190
- 默认启用.
191
-
192
- 配置 `cors`, 查看 [cors](https://github.com/expressjs/cors#configuration-options)
193
-
194
- - `options.log`
195
-
196
- **Type:** `boolean | 'info' | 'warn' | 'error' | 'silent'`
197
-
198
- 启动日志,以及配置日志打印级别
199
-
200
- - `options.formidableOptions`
201
-
202
- 配置 `formidable`,查看 [formidable options](https://github.com/node-formidable/formidable#options)
203
-
204
- **默认值:** `{}`
205
-
206
- 示例: 配置文件上传的存放目录
207
-
208
- ```ts
209
- MockDevServerPlugin({
210
- formidableOptions: {
211
- uploadDir: path.join(process.cwd(), 'uploads'),
212
- }
213
- })
214
- ```
215
-
216
- - `options.cookiesOptions`
217
-
218
- 配置 `cookies`, 查看 [cookies](https://github.com/pillarjs/cookies#new-cookiesrequest-response--options)
219
-
220
- **默认值:** `{}`
221
-
222
- - `options.bodyParserOptions`
223
-
224
- 配置 `co-body`, 查看 [co-body](https://github.com/cojs/co-body#options)
225
-
226
- - `options.build`
227
-
228
- 需要构建可独立部署的小型mock服务时配置。
229
-
230
- **类型:** `boolean | ServerBuildOptions`
231
-
232
- **默认值:**`false`
233
-
234
- ```ts
235
- interface ServerBuildOptions {
236
- /**
237
- * 服务端口
238
- * @default 8080
239
- */
240
- serverPort?: number
241
- /**
242
- * 构建输出目录
243
- * @default 'mockServer'
244
- */
245
- dist?: string
246
-
247
- /**
248
- * 日志级别
249
- * @default 'error'
250
- */
251
- log?: LogLevel
252
- }
253
- ```
254
-
255
- - `options.priority`
256
-
257
- 自定义 路径匹配规则优先级。[查看更多](#自定义匹配优先级)
258
-
259
- **默认值:** `undefined`
260
-
261
- ### defineMock(config)
262
-
263
- mock 配置帮助函数,提供类型检查帮助
264
-
265
- ```ts
266
- import { defineMock } from 'vite-plugin-mock-dev-server'
267
-
268
- export default defineMock({
269
- url: '/api/test',
270
- body: {}
271
- })
272
- ```
273
-
274
- ### createDefineMock(transformer)
275
-
276
- 返回一个自定义的 defineMock 函数,用于支持对 mock config 的预处理。
277
-
278
- ```ts
279
- import path from 'node:path'
280
- import { createDefineMock } from 'vite-plugin-mock-dev-server'
281
-
282
- // 预处理 mock url
283
- const defineAPIMock = createDefineMock((mock) => {
284
- mock.url = path.join('/api', mock.url)
285
- })
286
-
287
- export default defineApiMock({
288
- url: '/test' // 补全为 '/api/test'
289
- })
290
- ```
291
-
292
- ## Mock 配置
293
-
294
- ```ts
295
- // 配置 http mock
296
- export default defineMock({
297
- /**
298
- * 请求地址,支持 `/api/user/:id` 格式
299
- * 插件通过 `path-to-regexp` 匹配路径
300
- * @see https://github.com/pillarjs/path-to-regexp
301
- */
302
- url: '/api/test',
303
- /**
304
- * 接口支持的请求方法
305
- * @type string | string[]
306
- * @default ['POST','GET']
307
- *
308
- */
309
- method: ['GET', 'POST'],
310
- /**
311
- * 是否启用当前 mock请求
312
- * 在实际场景中,我们一般只需要某几个mock接口生效,
313
- * 而不是所以mock接口都启用。
314
- * 对当前不需要mock的接口,可设置为 false
315
- * @default true
316
- */
317
- enabled: true,
318
- /**
319
- * 设置接口响应延迟,如果传入的是一个数组,则代表延迟时间的范围
320
- * 单位:ms
321
- * @default 0
322
- */
323
- delay: 1000,
324
- /**
325
- * 响应状态码
326
- * @default 200
327
- */
328
- status: 200,
329
- /**
330
- * 响应状态文本
331
- */
332
- statusText: 'OK',
333
- /**
334
- * 响应状态 headers
335
- * @type Record<string, any>
336
- * @type (({ query, body, params, headers }) => Record<string, any>)
337
- * 入参部分为 请求相关信息
338
- */
339
- headers: {
340
- 'Content-Type': 'application/json'
341
- },
342
-
343
- /**
344
- * 响应体 cookies
345
- * @type Record<string, string | [value: string, option: CookieOption]>
346
- * @see https://github.com/pillarjs/cookies#cookiessetname--values--options
347
- */
348
- cookies: {
349
- 'your-cookie': 'your cookie value',
350
- 'cookie&option': ['cookie value', { path: '/', httpOnly: true }]
351
- },
352
-
353
- /**
354
- * 响应体数据类型, 可选值包括 `text, json, buffer`,
355
- * 还支持`mime-db`中的包含的类型。
356
- * 当响应体返回的是一个文件,而你不确定应该使用哪个类型时,可以将文件名作为值传入,
357
- * 插件内部会根据文件名后缀查找匹配的`content-type`。
358
- * 但如果是 `typescript`文件如 `a.ts`,可能不会被正确匹配为 `javascript`脚本,
359
- * 你需要将 `a.ts` 修改为 `a.js`作为值传入才能正确识别。
360
- * @see https://github.com/jshttp/mime-db
361
- * @default 'json'
362
- */
363
- type: 'json',
364
-
365
- /**
366
- * 响应体数据
367
- * 定义返回的响应体数据内容。
368
- * 在这里,你可以直接返回JavaScript支持的数据类型如 `string/number/array/object` 等
369
- * 同时,你也可以使用如 `mockjs` 等库来生成数据内容
370
- *
371
- * @type string | number | array | object
372
- * 直接返回定义的数据
373
- *
374
- * @type (request: { headers, query, body, params }) => any | Promise<any>
375
- * 如果传入一个函数,那么可以更加灵活的定义返回响应体数据
376
- */
377
- body: '',
378
-
379
- /**
380
- * 如果通过 body 配置不能解决mock需求,
381
- * 那么可以通过 配置 response,暴露http server 的接口,
382
- * 实现完全可控的自定义配置
383
- * 在 req参数中,已内置了 query、body、params 的解析,
384
- * 你可以直接使用它们。
385
- * 别忘了,需要通过 `res.end()` 返回响应体数据,
386
- * 或者需要跳过mock,那么别忘了调用 `next()`
387
- */
388
- response(req, res, next) {
389
- res.end()
390
- },
391
- /**
392
- * 请求验证器,通过验证器则返回 mock数据,否则不使用当前mock。
393
- * 这对于一些场景中,某个接口需要通过不同的入参来返回不同的数据,验证器可以很好的解决这一类问题,
394
- * 将同个 url 分为多个 mock配置,根据 验证器来判断哪个mock配置生效。
395
- *
396
- * @type { headers, body, query, params, refererQuery }
397
- * 如果 validator 传入的是一个对象,那么验证方式是 深度比较 请求的接口
398
- * 中 headers/body/query/params/refererQuery 是否包含 validator 的 key-value。
399
- *
400
- * @type (request) => boolean
401
- * 如果 validator 传入的是一个函数,那么会将 请求的接口相关数据作为入参,
402
- * 提供给使用者进行自定义校验,并返回一个 boolean
403
- *
404
- */
405
- validator: {
406
- headers: {},
407
- body: {},
408
- query: {},
409
- params: {},
410
- /**
411
- * refererQuery 验证了请求来源页面 URL 中的查询参数,
412
- * 这使得可以直接在浏览器地址栏中修改参数以获取不同的模拟数据。
413
- */
414
- refererQuery: {}
415
- },
416
- })
417
- ```
418
-
419
- ```ts
420
- // 配置 WebSocket mock
421
- export default defineMock({
422
- /**
423
- * 请求地址,支持 `/api/user/:id` 格式
424
- * 插件通过 `path-to-regexp` 匹配路径
425
- * @see https://github.com/pillarjs/path-to-regexp
426
- */
427
- url: '/api/test',
428
- /**
429
- * 必须显式的指定值为 `true`
430
- * 插件内部需要根据此值进行判断
431
- */
432
- ws: true,
433
- /**
434
- * 配置 WebSocketServer
435
- * @see https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocketserver
436
- * 如果在 setup 函数中有一些 额外的 自动执行任务或循环任务,
437
- * 那么需要在 `onCleanup()` 传入一个回调,用于清除这些任务,
438
- * 这是由于插件在热更新时,需要重新执行 setup,需要清除之前的任务,否则可能会导致重复任务产生冲突。
439
- * `onCleanup()`可以在 setup 内部多次调用
440
- * @type `(wss: WebSocketServer, context: SetupContext) => void`
441
- */
442
- setup(wss, { onCleanup }) {
443
- wss.on('connection', (ws, request) => {
444
- ws.on('message', (rawData) => {})
445
- const timer = setInterval(() => ws.send('data'), 1000)
446
- onCleanup(() => clearInterval(timer))
447
- })
448
- }
449
- })
450
- ```
451
-
452
- ### Request/Response 增强
453
-
454
- 当你配置 `headers`, `body`, and `response` 的函数形式时, 插件在参数 `request` 和 `response` 添加了新的内容用于帮助获取必要的数据.
455
-
456
- **Request:**
457
-
458
- `request`的原始数据类型是[`Connect.IncomingMessage`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/connect/index.d.ts). 插件在此基础上,增加了 `query`, `params`, `body`, `refererQuery`,以及 `getCookie(name)` 方法用于获取cookie信息。
459
-
460
- ```ts
461
- type Request = Connect.IncomingMessage & {
462
- query: object
463
- params: object
464
- body: any
465
- refererQuery: object
466
- getCookie: (name: string, option?: Cookies.GetOption) => string | undefined
467
- }
468
- ```
469
-
470
- **Response:**
471
-
472
- `response` 的原始数据类型是`http.ServerResponse<http.IncomingMessage>`. 插件在此基础上增加了 `setCookie(name, value)` 方法用于设置cookie
473
-
474
- ```ts
475
- type Response = http.ServerResponse<http.IncomingMessage> & {
476
- setCookie: (
477
- name: string,
478
- value?: string | null,
479
- option?: Cookies.SetOption,
480
- ) => void
481
- }
482
- ```
483
-
484
- > **注意:**
485
- >
486
- > 如果使用 json/json5 编写 mock文件,则不支持使用 `response` 方法,以及不支持使用其他字段的函数形式。
487
-
488
- ## 共享 Mock 数据
489
-
490
- 由于每个mock文件都是作为独立的入口进行编译,其依赖的本地文件也编译在内,
491
- 且每个mock文件拥有独立的作用域,这使得即使多个 mock文件共同依赖某一个`data.ts`文件,也无法共享数据。
492
- 某个 `mock` 文件对 `data.ts` 中的数据进行修改,其它`mock`文件不会获取到修改后的数据。
493
-
494
- 为此,插件提供了一个 `defineMockData` 函数,用于在 `mock` 文件中使用 `data.ts` 作为共享数据源。
495
-
496
- ```ts
497
- type defineMockData<T> = (
498
- key: string, // 数据唯一标识符
499
- initialData: T, // 初始化数据
500
- ) => [getter, setter] & { value: T }
501
- ```
502
-
503
- ### 用法
504
-
505
- `data.ts`
506
-
507
- ```ts
508
- import { defineMockData } from 'vite-plugin-mock-dev-server'
509
-
510
- export default defineMockData('posts', [
511
- { id: '1', title: 'title1', content: 'content1' },
512
- { id: '2', title: 'title2', content: 'content2' },
513
- ])
514
- ```
515
-
516
- `*.mock.ts`
517
-
518
- ```ts
519
- import { defineMock } from 'vite-plugin-mock-dev-server'
520
- import posts from './data'
521
-
522
- export default defineMock([
523
- {
524
- url: '/api/posts',
525
- body: () => posts.value
526
- },
527
- {
528
- url: '/api/posts/delete/:id',
529
- body: (params) => {
530
- const id = params.id
531
- posts.value = posts.value.filter(post => post.id !== id)
532
- return { success: true }
533
- }
534
- }
535
- ])
536
- ```
537
-
538
- > **注意:**
539
- >
540
- > `defineMockData` 仅是基于 `memory` 提供的共享数据支持,
541
- > 如果需要做 mock 数据持久化,建议使用 `nosql`, 如 `lowdb` 或 `level` 等。
542
-
543
- ## 自定义匹配优先级
544
-
545
- > 自定义规则仅影响包含动态参数的链接,如: `/api/user/:id`
546
-
547
- 插件内置的路径匹配规则优先级,已经能够满足大部分需求,但如果你需要更加灵活的自定义匹配规则优先级,
548
- 可以使用 `priority` 参数。
549
-
550
- 示例:
551
-
552
- ```ts
553
- import { defineConfig } from 'vite'
554
- import mockPlugin from 'vite-plugin-mock-dev-server'
555
-
556
- export default defineConfig({
557
- plugins: [
558
- mockPlugin({
559
- priority: {
560
- // 匹配规则优先级, 全局生效。声明在该选项中的规则将优先于默认规则生效。
561
- // 规则在数组越靠前的位置,优先级越高。
562
- global: ['/api/:a/b/c', '/api/a/:b/c', '/api/a/b/:c'],
563
- // 对于一些特殊情况,需要调整部分规则的优先级,可以使用此选项。
564
- // 比如一个请求同时命中了规则 A 和 B,且 A 比 B 优先级高, 但期望规则 B 生效时。
565
- special: {
566
- // 当请求同时命中 [key] 和 rules 中的任意一个时,优先匹配 [key] 。
567
- // when 用于进一步约束具体是哪些请求需要调整优先级。
568
- '/api/:a/:b/c': {
569
- rules: ['/api/a/:b/:c', '/api/a/b/:c'],
570
- when: ['/api/a/b/c']
571
- },
572
- // 如果不需要 when, 则表示命中规则的请求都需要调整优先级。
573
- // 可以简写为 [key]: [...rules]
574
- '/api/:a/b': ['/api/a/:b'],
575
- }
576
- }
577
- })
578
- ]
579
- })
580
- ```
581
-
582
- > **注意:**
583
- >
584
- > `priority` 虽然可以调整优先级,但大多数时候,你都没有必要这么做。
585
- > 对于一些特殊情况的请求,可以使用 静态规则来替代 `priority`,静态规则总是拥有最高优先级。
586
-
587
- ## Example
588
-
589
- `mock/**/*.mock.{ts,js,mjs,cjs,json,json5}`
590
-
591
- 查看更多示例: [example](/example/)
592
-
593
- **exp:** 命中 `/api/test` 请求,并返回一个 数据为空的响应体内容
594
-
595
- ```ts
596
- export default defineMock({
597
- url: '/api/test',
598
- })
599
- ```
600
-
601
- **exp:** 命中 `/api/test` 请求,并返回一个固定内容数据
602
-
603
- ```ts
604
- export default defineMock({
605
- url: '/api/test',
606
- body: { a: 1 },
607
- })
608
- ```
609
-
610
- ```ts
611
- export default defineMock({
612
- url: '/api/test',
613
- body: () => ({ a: 1 })
614
- })
615
- ```
616
-
617
- **exp:** 限定只允许 `GET` 请求
618
-
619
- ```ts
620
- export default defineMock({
621
- url: '/api/test',
622
- method: 'GET'
623
- })
624
- ```
625
-
626
- **exp:** 在返回的响应头中,添加自定义 header 和 cookie
627
-
628
- ```ts
629
- export default defineMock({
630
- url: '/api/test',
631
- headers: { 'X-Custom': '12345678' },
632
- cookies: { 'my-cookie': '123456789' },
633
- })
634
- ```
635
-
636
- ```ts
637
- export default defineMock({
638
- url: '/api/test',
639
- headers({ query, body, params, headers }) {
640
- return { 'X-Custom': query.custom }
641
- },
642
- cookies() {
643
- return { 'my-cookie': '123456789' }
644
- }
645
- })
646
- ```
647
-
648
- **exp:** 定义多个相同url请求mock,并使用验证器匹配生效规则
649
-
650
- ```ts
651
- export default defineMock([
652
- // 命中 /api/test?a=1
653
- {
654
- url: '/api/test',
655
- validator: {
656
- query: { a: 1 },
657
- },
658
- body: { message: 'query.a === 1' },
659
- },
660
- // 命中 /api/test?a=2
661
- {
662
- url: '/api/test',
663
- validator: {
664
- query: { a: 2 },
665
- },
666
- body: { message: 'query.a === 2' },
667
- },
668
- {
669
- // `?a=3` 将会解析到 `validator.query`
670
- url: '/api/test?a=3',
671
- body: { message: 'query.a == 3' },
672
- },
673
- // 命中 POST /api/test 请求,且 请求体中,字段 a 为数组,且数组包含值为 1, 2 的项
674
- {
675
- url: '/api/test',
676
- method: ['POST'],
677
- validator: { body: { a: [1, 2] } }
678
- }
679
- ])
680
- ```
681
-
682
- **exp:** 延迟接口响应:
683
-
684
- ```ts
685
- export default defineMock({
686
- url: '/api/test',
687
- delay: 6000, // 延迟 6秒
688
- })
689
- ```
690
-
691
- **exp:** 使接口请求失败
692
-
693
- ```ts
694
- export default defineMock({
695
- url: '/api/test',
696
- status: 502,
697
- statusText: 'Bad Gateway'
698
- })
699
- ```
700
-
701
- **exp:** 动态路由匹配
702
-
703
- ```ts
704
- export default defineMock({
705
- url: '/api/user/:userId',
706
- body({ params }) {
707
- return { userId: params.userId }
708
- }
709
- })
710
- ```
711
-
712
- 路由中的 `userId`将会解析到 `request.params` 对象中.
713
-
714
- **exp:** 使用 buffer 响应数据
715
-
716
- ```ts
717
- import { Buffer } from 'node:buffer'
718
-
719
- // 由于 type 默认值是 json,虽然在传输过程中body使用buffer,
720
- // 但是 content-type 还是为 json
721
- export default defineMock({
722
- url: 'api/buffer',
723
- body: Buffer.from(JSON.stringify({ a: 1 }))
724
- })
725
- ```
726
-
727
- ```ts
728
- // 当 type 为 buffer 时,content-type 为 application/octet-stream,
729
- // body 传入的数据会被转为 buffer
730
- export default defineMock({
731
- url: 'api/buffer',
732
- type: 'buffer',
733
- // 内部使用 Buffer.from(body) 进行转换
734
- body: { a: 1 }
735
- })
736
- ```
737
-
738
- **exp:** 响应文件类型
739
-
740
- 模拟文件下载,传入文件读取流
741
-
742
- ```ts
743
- import { createReadStream } from 'node:fs'
744
-
745
- export default defineMock({
746
- url: '/api/download',
747
- // 当你不确定类型,可传入文件名由插件内部进行解析
748
- type: 'my-app.dmg',
749
- body: () => createReadStream('./my-app.dmg')
750
- })
751
- ```
752
-
753
- ```html
754
- <a href="/api/download" download="my-app.dmg">下载文件</a>
755
- ```
756
-
757
- **exp:** 使用 `mockjs` 生成响应数据:
758
-
759
- ```ts
760
- import Mock from 'mockjs'
761
-
762
- export default defineMock({
763
- url: '/api/test',
764
- body: Mock.mock({
765
- 'list|1-10': [{
766
- 'id|+1': 1
767
- }]
768
- })
769
- })
770
- ```
771
-
772
- 请先安装 `mockjs`
773
-
774
- **exp:** 使用 `response` 自定义响应
775
-
776
- ```ts
777
- export default defineMock({
778
- url: '/api/test',
779
- response(req, res, next) {
780
- const { query, body, params, headers } = req
781
- console.log(query, body, params, headers)
782
-
783
- res.status = 200
784
- res.setHeader('Content-Type', 'application/json')
785
- res.end(JSON.stringify({
786
- query,
787
- body,
788
- params,
789
- }))
790
- }
791
- })
792
- ```
793
-
794
- **exp:** 使用 json / json5
795
-
796
- ```json
797
- {
798
- "url": "/api/test",
799
- "body": {
800
- "a": 1
801
- }
802
- }
803
- ```
804
-
805
- **exp:** multipart, 文件上传.
806
-
807
- 通过 [`formidable`](https://www.npmjs.com/package/formidable#readme) 支持。
808
-
809
- ``` html
810
- <form action="/api/upload" method="post" enctype="multipart/form-data">
811
- <p>
812
- <span>file: </span>
813
- <input type="file" name="files" multiple="multiple">
814
- </p>
815
- <p>
816
- <span>name:</span>
817
- <input type="text" name="name" value="mark">
818
- </p>
819
- <p>
820
- <input type="submit" value="submit">
821
- </p>
822
- </form>
823
- ```
824
-
825
- fields `files` 映射为 `formidable.File` 类型。
826
-
827
- ``` ts
828
- export default defineMock({
829
- url: '/api/upload',
830
- method: 'POST',
831
- body(req) {
832
- const body = req.body
833
- return {
834
- name: body.name,
835
- files: body.files.map((file: any) => file.originalFilename),
836
- }
837
- },
838
- })
839
- ```
840
-
841
- **exp:** Graphql
842
-
843
- ```ts
844
- import { buildSchema, graphql } from 'graphql'
845
-
846
- const schema = buildSchema(`
847
- type Query {
848
- hello: String
849
- }
850
- `)
851
- const rootValue = { hello: () => 'Hello world!' }
852
-
853
- export default defineMock({
854
- url: '/api/graphql',
855
- method: 'POST',
856
- body: async (request) => {
857
- const source = request.body.source
858
- const { data } = await graphql({ schema, rootValue, source })
859
- return data
860
- },
861
- })
862
- ```
863
-
864
- ```ts
865
- fetch('/api/graphql', {
866
- method: 'POST',
867
- body: JSON.stringify({ source: '{ hello }' })
868
- })
869
- ```
870
-
871
- **exp:** WebSocket Mock
872
-
873
- ```ts
874
- // ws.mock.ts
875
- export default defineMock({
876
- url: '/socket.io',
877
- ws: true,
878
- setup(wss, { onCleanup }) {
879
- const wsMap = new Map()
880
- wss.on('connection', (ws, req) => {
881
- const token = req.getCookie('token')
882
- wsMap.set(token, ws)
883
- ws.on('message', (raw) => {
884
- const data = JSON.parse(String(raw))
885
- if (data.type === 'ping')
886
- return
887
- // Broadcast
888
- for (const [_token, _ws] of wsMap.entires()) {
889
- if (_token !== token)
890
- _ws.send(raw)
891
- }
892
- })
893
- })
894
- wss.on('error', (err) => {
895
- console.error(err)
896
- })
897
- onCleanup(() => wsMap.clear())
898
- }
899
- })
900
- ```
901
-
902
- ```ts
903
- // app.ts
904
- const ws = new WebSocket('ws://localhost:5173/socket.io')
905
- ws.addEventListener('open', () => {
906
- setInterval(() => {
907
- // heartbeat
908
- ws.send(JSON.stringify({ type: 'ping' }))
909
- }, 1000)
910
- }, { once: true })
911
- ws.addEventListener('message', (raw) => {
912
- console.log(raw)
913
- })
914
- ```
915
-
916
- ## 独立部署的小型mock服务
917
-
918
- 在一些场景中,可能会需要使用mock服务提供的数据支持,用于展示,但可能项目已完成打包构建部署,已脱离 `vite` 和本插件提供的 mock服务支持。由于本插件在设计之初,支持在mock文件中引入各种 `node` 模块,所以不能将 mock文件打包内联到客户端构建代码中。
919
-
920
- 为了能够满足这类场景,插件一方面提供了 `vite preview` 下的支持,同时还提供了在 `vite build` 时,也构建一个可独立部署的 小型mock服务应用,可以将这个应用部署到相关的环境,后通过其他http服务器如nginx做代理转发到实际端口实现mock支持。
921
-
922
- 构建默认输出到 `dist/mockServer` 目录中,并生成如下文件:
923
-
924
- ```sh
925
- ./mockServer
926
- ├── index.js
927
- ├── mock-data.js
928
- └── package.json
929
- ```
930
-
931
- 在该目录下,执行 `npm install` 安装依赖后,执行 `npm start` 即可启动 mock server。
932
- 默认端口为 `8080`。
933
- 可通过 `localhost:8080/` 访问相关的 `mock` 接口。
934
-
935
- ## Archives
936
-
937
- [awesome-vite](https://github.com/vitejs/awesome-vite#helpers)
938
-
939
- ## LICENSE
940
-
941
- [MIT](/LICENSE)
942
-
943
- [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fpengzhanbo%2Fvite-plugin-mock-dev-server.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fpengzhanbo%2Fvite-plugin-mock-dev-server?ref=badge_large)