You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,测试环境用完整域名,生产环境用相对路径:

  1. 在项目根目录创建.env.test文件:
VITE_APP_API_BASE_URL=http://localhost:5173/api
  1. 修改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"]
    }),
  }),
});
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:54:59