如何使用mswjs模拟外部域名/资源 同时支持本地资源mock的配置方法
MSW + Storybook 同时Mock本地localhost和外部API配置方案
完全支持该场景,MSW会根据你定义的请求匹配规则拦截所有符合条件的请求,和目标域名是否为localhost无关,以下是可直接复用的配置示例:
1. 定义全局请求处理规则
// mocks/handlers.js import { rest } from 'msw' export const handlers = [ // 匹配本地localhost接口示例 rest.get('/api/user', (req, res, ctx) => { return res(ctx.json({ id: 1, name: '本地测试用户', role: 'admin' })) }), // 匹配非localhost的外部API示例,写完整的接口绝对路径即可 rest.get('https://api.external-service.com/v2/products', (req, res, ctx) => { return res(ctx.json({ list: [ { id: 101, name: '外部商品A', price: 99 }, { id: 102, name: '外部商品B', price: 199 } ], total: 2 })) }), // 也支持匹配外部API的动态路径 rest.get('https://api.another-service.com/users/:userId', (req, res, ctx) => { const { userId } = req.params return res(ctx.json({ id: userId, nickname: '外部平台用户' })) }) ]
2. Storybook全局注册MSW插件
// .storybook/preview.js import { initialize, mswDecorator } from 'msw-storybook-addon' import { handlers } from '../mocks/handlers' // 初始化MSW,传入全局共用的handler initialize({ handlers: handlers }) export const decorators = [mswDecorator] // 其余Storybook全局配置保留即可 export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }
注意事项
- 外部API的匹配规则必须写完整的绝对路径,如果只写相对路径(比如
/v2/products),MSW会默认拼接当前页面域名(localhost),无法匹配到外部域名的请求 - MSW在浏览器层面拦截请求,不会触发跨域CORS报错,不需要额外配置服务端跨域规则
- 未命中handler规则的请求会直接走真实网络请求,不需要额外配置透传逻辑
可选:单个Story自定义Mock规则
如果某个场景需要覆盖全局的Mock返回,可以直接在单条Story的参数中单独定义handler:
// 某个组件的stories.js文件 import ProductList from './ProductList' export default { title: 'Components/ProductList', component: ProductList, } const Template = (args) => <ProductList {...args} /> export const EmptyProductList = Template.bind({}) EmptyProductList.parameters = { msw: [ // 覆盖全局的外部接口返回,返回空列表 rest.get('https://api.external-service.com/v2/products', (req, res, ctx) => { return res(ctx.json({ list: [], total: 0 })) }) ] }
内容的提问来源于stack exchange,提问作者Fez Vrasta
相关产品推荐
相关产品推荐

