外观
同一份 Mock,开发与静态演示
目标:让接口未就绪时仍可完成页面,并让构建后的演示在没有 API 服务时运行。
请求在哪里执行
| 命令 | 处理位置 | 状态寿命 |
|---|---|---|
pnpm dev | Vite Mock 服务,Node 进程 | 服务重启后恢复种子 |
pnpm build:demo + pnpm preview | 浏览器 Axios adapter | 当前浏览器跨刷新保留 |
pnpm build / pnpm dev:unode | 真实 API | 由服务端负责 |
浏览器 adapter 只在 VITE_DEMO=true 时加载。它匹配请求方法、路径、query、JSON、动态参数与 FormData,未知 API 返回明确错误,不回退网络。
新增处理器
在 apps/demo/mock/ 新建 *.mock.ts,使用共享包装器:
ts
import { defineMock } from './_define'
import { ok, fail } from './_envelope'
export default defineMock({
url: '/api/reports/:id',
method: 'GET',
body: ({ params }) => {
if (params.id !== 'monthly') return fail('报表不存在', 'NOT_FOUND', 404)
return ok({ id: 'monthly', total: 128 })
},
})先在 API 文件定义 DTO,再确保处理器使用相同字段。新资源还需在 _define.ts 的权限映射登记;包装器统一完成授权与开发 HTTP 状态输出。客户端使用 /reports/monthly,Mock 使用含 API 前缀的 /api/reports/:id。
可变数据如何保存
共享状态函数位于 packages/modules/src/mock/storage.ts。persisted(key, seed) 为种子创建稳定根引用;浏览器 adapter 串行执行变更并写入版本化快照,写盘失败回滚内存。Node 环境使用内存。
新增列表应对已登记数组使用 push、splice 等原地变更,不要给闭包变量换一个新数组而让持久化注册表仍指向旧对象。参数验证在变更之前完成,批量导入也应先验证全部记录。
文件与模拟行为
apps/demo/mock/files.ts 将 Blob 放进专用 IndexedDB。业务状态保存 demo-file: 引用,返回响应时转换成当前页面可用的 Blob URL。开发上传由 multipart 解析器提供文件,共享包装器归一化单值字段。
注册与找回密码使用固定演示验证码,聊天回复为本地生成;模块安装改变演示状态,不下载或执行插件。地图和 MQTT 默认提供模拟体验,真实外部服务需显式配置。
验证两条路径
bash
pnpm exec vitest run apps/demo/mock/browser.test.ts
pnpm build:demo
pnpm test:e2e:static另外在 pnpm dev 中走一次相同流程,特别是文件上传:Node multipart 与浏览器 FormData 的输入形状不同。
新增接口返回 404: 检查文件后缀、URL 前缀和 method。刷新丢数据: 检查是否登记 persisted 以及是否替换了根引用。新增种子菜单不出现: 已保存菜单优先于新种子,演示重置后再试。真实版本出现演示账号: 构建后运行 node scripts/check-demo-bundle.mjs apps/demo/dist。