现代前端开发中,后端接口往往不能第一时间就绪。如果前端页面已经写好,却因为没有数据而无法调试,开发效率就会大打折扣。“Mock”就是用来解决这个问题的:在前端模拟出符合接口约定的假数据,让开发可以在无后端的情况下独立推进。好的 Mock 方案不仅要能模拟数据,还要能平滑切换到真实接口,并且在联调阶段让问题快速暴露。
常见的 Mock 方案与选型建议
| 方案 | 特点 | 适用场景 |
|------|------|----------|
| 本地手写 Mock 数据 | 直接在代码中定义 JSON 对象,模拟接口返回。 | 极简单页面或一次性 Demo |
| Mock.js | 拦截 XMLHttpRequest/fetch,根据规则生成随机中文、数字等。 | 需要大量随机测试数据、快速原型 |
| vite-plugin-mock | Vite 插件,在开发服务器中注入 Mock 路由,本地开发时启用。 | Vite + Vue 项目,希望 Mock 与真实接口无缝切换 |
| Mock Service Worker (MSW) | 利用 Service Worker 在浏览器网络层拦截请求,不影响应用代码,甚至可以用于测试。 | 对接口模拟的真实性要求高,同时需要用于单元/组件测试 |
| json-server | 将 JSON 文件暴露为 RESTful API,支持增删改查。 | 快速原型,或需要一个临时的后端服务 |
| 契约平台 (Swagger/YApi) | 由后端生成或前后端共同维护的接口文档平台,可自动生成 Mock 数据。 | 团队协作,需要接口一致性保障 |
实用的选择策略:大多数 Vite + Vue 3 项目,推荐 vite-plugin-mock 作为本地 Mock 方案,因为它配置简单,Mock 文件集中管理,且产生的是真实网络请求(不会被浏览器拦截),切换真实接口时只需要关掉插件或修改环境变量。如果项目中还涉及组件测试,可以补充 MSW 来在测试环境中模拟接口。
vite-plugin-mock 实战
安装与配置
npm install vite-plugin-mock mockjs -D
在 vite.config.ts 中引入插件:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteMockServe } from 'vite-plugin-mock'
export default defineConfig({
plugins: [
vue(),
viteMockServe({
mockPath: 'mock', // mock 文件存放目录
enable: true, // 是否开启 mock(开发环境建议为 true)
logger: true, // 是否在控制台打印请求日志
})
]
})
编写 Mock 文件
在项目根目录创建 mock 文件夹,例如 mock/user.ts:
import { MockMethod } from 'vite-plugin-mock'
export default [
{
url: '/api/user/info',
method: 'get',
response: () => {
return {
code: 200,
data: {
id: 1,
name: '张三',
avatar: 'https://example.com/avatar.jpg',
role: 'admin'
}
}
}
},
{
url: '/api/user/login',
method: 'post',
response: ({ body }) => {
// 可以根据请求 body 返回不同数据
const { username, password } = body
if (username === 'admin' && password === '123456') {
return {
code: 200,
data: { token: 'mock-token-xxxx' }
}
}
return { code: 401, message: '用户名或密码错误' }
}
}
] as MockMethod[]
文件导出一个数组,每个对象包含url(支持正则)、method、response(可以是函数,接收{ body, query, headers })。你可以直接返回静态数据,也可以配合 Mock.js 生成随机中文、数字、日期,让数据更真实:
import Mock from 'mockjs'
response: () => {
return Mock.mock({
'list|5-10': [{ // 生成 5~10 条数据
'id|+1': 1,
'name': '@cname', // 中文姓名
'email': '@email',
'createTime': '@datetime'
}]
})
}
效果:启动 npm run dev 后,前端请求 /api/user/info 会被 Vite 本地服务器拦截并返回 Mock 数据。你可以在浏览器 Network 面板中看到这个请求,与真实请求无二。
用环境变量控制切换
为了在联调时快速切换为真实后端,我们可以在 .env.development 中控制:
VITE_MOCK_ENABLED=true # 开发时开启 Mock,联调时改为 false
在 vite.config.ts 中读取环境变量:
const isMock = process.env.VITE_MOCK_ENABLED === 'true'
export default defineConfig({
plugins: [
vue(),
viteMockServe({
enable: isMock,
// ...
})
]
})
这样前端代码中一律请求真实接口路径(如 /api/user/info),无需改写任何地址,Mock 只是在网络层拦截。切换到真实后端时,关闭 Mock,Vite 默认会将 /api 开头的请求代理到后端服务(需配置 server.proxy)。
前后端联调流程
即使有 Mock,前后端最终还是要合在一起验证。一套顺畅的联调流程可以大幅减少“我那没问题,你这咋挂了”的扯皮。
1. 接口约定先行
前后端需要以接口文档作为唯一真理源。推荐使用 Swagger (OpenAPI) 或 YApi 等工具,由后端产出(或前后端共同维护)。文档中需明确:URL、请求方法、请求参数格式、返回数据结构及字段含义、错误码约定。接口文档一旦冻结,前端就可以依此编写 Mock 和业务代码,后端据此实现。
2. 并行开发阶段
- 前端:按文档在
mock/中构建 Mock 数据,开发页面逻辑。Mock 数据要覆盖正常/异常/边界场景(如空列表、权限错误、超时),确保界面健壮。 - 后端:编码实现真实接口,并使用 Postman 或单元测试自测通过。
3. 联调准备
- 前端关闭 Mock(例如修改
.env.development中VITE_MOCK_ENABLED=false),配置 Vite 的代理将/api转发到后端开发服务器:
// vite.config.ts
server: {
proxy: {
'/api': {
target: 'http://192.168.1.100:8080', // 后端地址
changeOrigin: true,
}
}
}
- 后端确保开发服务器已启动,并打通网络(同事能访问)。
4. 联调阶段
- 按模块逐步对接:不要等所有接口都好了才联调,可以按功能模块(如登录、用户列表)逐个对接。
- 数据驱动调试:前端打开浏览器 Network 面板,观察返回数据是否符合预期;有偏差立即截图或复制响应内容反馈给后端。
- 错误统一处理:利用 Axios 响应拦截器对 401、500 等状态码做全局处理,联调时很容易发现后端的异常状态码是否与约定一致。
- Mock 与真实接口的差异:最常出现的坑是字段名大小写、类型(比如后端返回
'1'而前端期望1)、空值形式(nullvs 空数组)。加强接口文档的细节描述,或者在联调初期故意将 Mock 数据写得更贴近文档,而非更“方便”。
5. 测试与验收
联调完成后,前端需在真实数据下跑通全部流程,特别关注:
- 列表分页参数是否正确
- 文件上传接口的跨域、超时处理
- 长时间无操作后 Token 过期时的重定向
进阶实践:Mock 数据与测试共存
如果项目中使用 MSW 进行组件测试,可以将 Mock 收敛到 mocks/handlers.js 文件中,开发时通过 MSW 的 browser 集成启用,测试时用 setupServer 启用,做到同一份 Mock 数据驱动力开发和单元测试。但多数 Vue 项目仅需要 vite-plugin-mock 就足够省心。
核心准则:Mock 的目的是让前端脱离后端束缚,但它永远不应脱离接口约定的约束。保持 Mock 数据与文档对齐,才能换来联调时的丝滑过渡。