Vite项目集成MSW与RTK Query时baseUrl设为/api失效求助
问题描述
在基于Vite+RTK Query的项目中集成MSW进行测试时,遇到baseUrl兼容问题:
- 未引入MSW时,RTK Query的
baseUrl设为/api可正常运行 - 引入MSW后,仅当RTK Query的
baseUrl改为完整地址http://localhost:5173/api时,才能与MSW的handler匹配 - 希望保持RTK Query的
baseUrl为/api,同时让MSW能正常拦截请求,避免部署时需额外配置环境变量的麻烦
原RTK Query配置(authSlice.ts)
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; import { User } from './userSlice' export const authSlice = createApi({ reducerPath: "auth", baseQuery: fetchBaseQuery({ baseUrl: "/api" }), tagTypes: ["Auth"], endpoints: (builder) => ({ getAuth: builder.query<User, void>({ query: () => "/auth", providesTags: ["Auth"] }), }), }); export const { useGetAuthQuery } = authSlice; export type useGetAuthQueryResult = ReturnType<typeof useGetAuthQuery>
原MSW配置
import { User } from '../../Store/RTK/userSlice' import { rest } from 'msw' import { setupServer } from 'msw/node' export const handlers = [ rest.get('http://localhost:5173/api/users', (_, res, ctx) => { const testUser: Partial<User> = { id: '1', username: 'test user' } return res( ctx.status(200), ctx.json([testUser]) ) }), rest.get('http://localhost:5173/api/auth', (_, res, ctx) => { const testAuthUser: Partial<User> = { id: '0', username: 'test auth user' } return res( ctx.status(200), ctx.json(testAuthUser) ) }) ] export const server = setupServer(...handlers)
解决方案
方案1:MSW使用正则匹配路径(无需修改RTK配置)
直接修改MSW的handler,用正则表达式匹配URL的路径部分,摆脱对域名的依赖:
export const handlers = [ rest.get(/\/api\/users$/, (_, res, ctx) => { const testUser: Partial<User> = { id: '1', username: 'test user' } return res( ctx.status(200), ctx.json([testUser]) ) }), rest.get(/\/api\/auth$/, (_, res, ctx) => { const testAuthUser: Partial<User> = { id: '0', username: 'test auth user' } return res( ctx.status(200), ctx.json(testAuthUser) ) }) ]
此方案下,无论RTK Query使用/api还是完整域名的baseUrl,只要请求路径匹配,MSW都会拦截并返回模拟数据。
方案2:环境变量控制RTK baseUrl(适配多环境)
通过Vite的环境变量,为不同环境设置不同的baseUrl,测试环境用完整域名,生产环境用相对路径:
- 在项目根目录创建
.env.test文件:
VITE_APP_API_BASE_URL=http://localhost:5173/api
- 修改RTK Query的baseUrl配置:
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; import { User } from './userSlice' // 优先读取环境变量,默认使用相对路径 const baseUrl = import.meta.env.VITE_APP_API_BASE_URL || '/api'; export const authSlice = createApi({ reducerPath: "auth", baseQuery: fetchBaseQuery({ baseUrl }), tagTypes: ["Auth"], endpoints: (builder) => ({ getAuth: builder.query<User, void>({ query: () => "/auth", providesTags: ["Auth"] }), }), });
- MSW的handler也可通过环境变量复用baseUrl:
import { User } from '../../Store/RTK/userSlice' import { rest } from 'msw' import { setupServer } from 'msw/node' const apiBaseUrl = import.meta.env.VITE_APP_API_BASE_URL || 'http://localhost:5173/api'; export const handlers = [ rest.get(`${apiBaseUrl}/users`, (_, res, ctx) => { const testUser: Partial<User> = { id: '1', username: 'test user' } return res( ctx.status(200), ctx.json([testUser]) ) }), rest.get(`${apiBaseUrl}/auth`, (_, res, ctx) => { const testAuthUser: Partial<User> = { id: '0', username: 'test auth user' } return res( ctx.status(200), ctx.json(testAuthUser) ) }) ] export const server = setupServer(...handlers)
方案3:MSW使用动态路径匹配(最灵活)
利用MSW的函数式匹配规则,忽略域名仅检查请求路径:
export const handlers = [ rest.get((url) => url.pathname === '/api/users', (_, res, ctx) => { const testUser: Partial<User> = { id: '1', username: 'test user' } return res( ctx.status(200), ctx.json([testUser]) ) }), rest.get((url) => url.pathname === '/api/auth', (_, res, ctx) => { const testAuthUser: Partial<User> = { id: '0', username: 'test auth user' } return res( ctx.status(200), ctx.json(testAuthUser) ) }) ]
此方式完全脱离域名限制,任何域名下的/api/auth或/api/users请求都会被MSW拦截。
内容的提问来源于stack exchange,提问作者Jiayu Zhang
相关产品推荐
相关产品推荐

