1.1 MSW 是什么
… 正在启动 Mock Worker🌐 本教程的在线站点:https://yzhijie.github.io/msw-tutorial/ ,其中漫画剧场也一并部署;每次向源码仓库推送 main,站点会由 Actions 自动重新构建发布。
Mock Service Worker(MSW) 是一个 API 模拟工具:它使用 Service Worker(浏览器)或 请求拦截(Node) 在应用的网络层截获请求,并用你编写的 handler 返回模拟响应。
应用代码完全无感知 —— 你写的还是普通的 fetch("/api/users"),浏览器 DevTools 的 Network 面板里甚至能看到这条"请求"以及它的状态码、响应头和响应体。
为什么需要它
在前后端分离的项目里,前端开发常常面临:
| 痛点 | 传统做法(手写 mock / json-server / 改代码) | MSW 的做法 |
|---|---|---|
| 后端接口没就绪 | 业务代码里写死假数据,联调前再删 | 真实发请求,网络层返回,业务代码零侵入 |
| 想测 500 / 超时 | 手动改代码或后端配合 | 一个开关切换错误状态与延迟 |
| 单元测试 mock 与开发 mock 两套 | vi.mock 与 mock 文件各写一份 | 同一套 handler,浏览器和 Node 共用 |
| DevTools 看不到请求 | 数据凭空出现,难以排查 | 请求真实经过网络栈,Network 面板完整可见 |
| 想模拟 WebSocket | 依赖 mock-socket 等三方库 | MSW 3 内置原生 WebSocket 拦截 |
核心理念一句话:mock 应该发生在网络边界上,而不是散落在应用代码里。
工作原理(浏览器)
你的应用 浏览器网络栈 真实服务器
┌──────────┐ fetch() ┌─────────────────────┐
│ 业务代码 │ ───────────▶ │ Service Worker 注册 │
│ (无感知) │ │ mockServiceWorker │
└──────────┘ └─────────┬───────────┘ ┌──────────┐
▲ │ 匹配 handler? │ 后端 API │
│ Response ▼ └──────────┘
│ ┌─────────────────┐
└────────────────────│ 你的 handlers │
状态码/头/JSON/延迟 │ http/ws/graphql │
└─────────────────┘
│ 未匹配
▼
passthrough() → 放行到真实服务器三个角色(本教程漫画「信标驿站」里的拟人化设定):
- 请求小邮差:你应用发出的每个 HTTP / WS 请求。
- Worker 站长:注册在页面同源下的
mockServiceWorker.js,所有出域请求先经过它,按规则决定"自己回信"还是"放行"。 - 服务端大熊:真实后端(或 MSW 在 Node 测试里扮演的拦截层)。
MSW 3 的关键变化(v2 → v3 迁移要点)
本教程基于 MSW 3.0.x,如果你见过 v1/v2 的教程,以下差异必须记住:
- 命名空间按协议拆分子路径:
http、HttpResponse仍从msw导入;graphql改为从msw/graphql导入(并需要 peer 依赖graphql);- WebSocket 的
ws从msw/ws导入。
- 原生 WebSocket:
ws.link("ws://…")+ 事件驱动 API,不再需要 mock-socket。 onUnhandledRequest更名为onUnhandledFrame,统一表示"未处理的 HTTP 请求 / WS 帧"。- handler 数组类型用
AnyHandler[](HTTP 与 WS handler 的联合)。 - 浏览器客户端事件只有
open/message/close(没有独立error事件上的帧语义,错误通过关闭码表达)。 - 官方提供
msw/vite插件(virtual:msw)作为可选的零文件集成方式;本教程使用经典的public/mockServiceWorker.js方式,原理更透明。
本教程怎么学
- 第二章:5 分钟把 worker 跑起来;
- 第三 ~ 六章:按"启动 → 拦截 → 响应 → 高级"的顺序系统讲解 API;
- 第七章:综合场景与交互实验室 —— 本页面右上角的徽章如果显示"拦截中",说明你此刻就可以直接在文档里发请求。
想要完整工程?仓库提供两个功能完全对等的独立可运行示例:
bash
pnpm dev:react # http://localhost:5173 React 19 + TypeScript
pnpm dev:vue # http://localhost:5174 Vue 3.5 + Pinia + TypeScript不想 clone 仓库?也可以在 StackBlitz(WebContainers)中在线打开整个 monorepo 运行: 在 StackBlitz 中打开。 (仓库为私有访问时,需先在 StackBlitz 登录 GitHub 并完成授权。)