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

Vite PWA中无法同时注册Mock Service Worker与其他Service Worker问题

React+Vite PWA项目中MSW请求拦截失效及多Service Worker共存问题

一、当前配置与问题现状

已按MSW官方文档完成配置,定义了如下请求处理器:

import { rest } from 'msw'

export const handlers = [
  rest.post('/login', (req, res, ctx) => {
    console.log('req', req)
    sessionStorage.setItem('is-authenticated', 'true')
    return res(ctx.status(200))
  }),

  rest.get('/user', (_, res, ctx) => {
    const isAuthenticated = sessionStorage.getItem('is-authenticated')
    if (!isAuthenticated) {
      return res(
        ctx.status(403),
        ctx.json({ errorMessage: 'Not authorized' })
      )
    }
    return res(
      ctx.status(200),
      ctx.json({ username: 'admin' })
    )
  }),
]

启动Worker代码:

async function main() {
  console.log(process.env.NODE_ENV)
  if (process.env.NODE_ENV === 'development') {
    await worker.start({ onUnhandledRequest: 'warn' })
    worker.printHandlers()
  }

  const queryClient = new QueryClient()
  const router = createBrowserRouter([
    { path: '/', element: <SignIn /> },
    { path: '/dashboard', element: <div>Hello dashboard here!</div> },
  ])

  ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
      <QueryClientProvider client={queryClient}>
        <RouterProvider router={router} />
      </QueryClientProvider>
    </React.StrictMode>,
  )
}

问题1:MSW请求拦截失效

浏览器中已确认mockServiceWorker.js可正常访问,处理器信息也打印到控制台,但发起以下请求时MSW未拦截:

const mutation = useMutation({
    mutationFn: (data: FormData) => {
      console.log('data', data)
      return axios.post('/login', data)
    },
    onSuccess: () => navigate('/dashboard'),
  })

问题2:多Service Worker注册冲突

dev-dist目录下registerSW.js中的PWA Service Worker注册代码阻碍了MSW注册:

if('serviceWorker' in navigator) navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' })

注释该代码后MSW可正常注册,但需要同时启用两个Service Worker。


二、MSW拦截失效排查与解决

排查方向

  • 请求匹配校验:查看浏览器Network面板,确认axios发起的请求URL、方法是否与MSW处理器完全一致(比如是否自动添加了baseURL前缀)。
  • Worker注册顺序:PWA SW先注册会抢占根作用域,导致MSW无法拦截请求。
  • 请求绕过检查:确认axios未配置绕过Service Worker的选项(比如使用Node.js HTTP适配器)。
  • MSW日志分析:查看控制台中onUnhandledRequest的警告信息,确认请求未匹配的原因。

解决步骤

  1. 修正请求匹配规则
    如果axios配置了baseURL(如axios.defaults.baseURL = '/api'),需将MSW处理器路径改为对应前缀,比如rest.post('/api/login', ...),或在开发环境临时移除baseURL配置。

  2. 调整Worker启动顺序
    将MSW启动逻辑放在PWA SW注册之前,确保MSW先完成注册:

    async function main() {
      console.log(process.env.NODE_ENV)
      if (process.env.NODE_ENV === 'development') {
        // 先启动MSW
        await worker.start({ onUnhandledRequest: 'warn' })
        worker.printHandlers()
      }
    
      // 再注册PWA SW(仅开发环境,生产环境单独处理)
      if ('serviceWorker' in navigator && process.env.NODE_ENV === 'development') {
        navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' })
      }
    
      // 后续渲染逻辑不变
      const queryClient = new QueryClient()
      const router = createBrowserRouter([
        { path: '/', element: <SignIn /> },
        { path: '/dashboard', element: <div>Hello dashboard here!</div> },
      ])
    
      ReactDOM.createRoot(document.getElementById('root')!).render(
        <React.StrictMode>
          <QueryClientProvider client={queryClient}>
            <RouterProvider router={router} />
          </QueryClientProvider>
        </React.StrictMode>,
      )
    }
    
  3. 移除axios绕过配置
    检查axios是否存在以下配置,若有则删除:

    // 该配置会使用Node.js HTTP模块发起请求,绕过浏览器Service Worker
    axios.defaults.adapter = require('axios/lib/adapters/http')
    

三、同时注册MSW与PWA Service Worker方案

方案1:环境区分注册

开发环境仅启用MSW,生产环境仅启用PWA SW,避免冲突:

async function main() {
  if (process.env.NODE_ENV === 'development') {
    await worker.start({ onUnhandledRequest: 'warn' })
    worker.printHandlers()
  } else {
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js', { scope: '/', type: 'classic' })
    }
  }

  // 渲染逻辑...
}

方案2:作用域隔离

给PWA SW设置更窄的作用域(如/assets/),让MSW负责拦截业务请求,PWA SW仅缓存静态资源:

  1. 修改registerSW.js:
    if('serviceWorker' in navigator) {
      navigator.serviceWorker.register('/dev-sw.js?dev-sw', { 
        scope: '/assets/', 
        type: 'classic' 
      })
    }
    
  2. 调整Vite PWA插件配置,让PWA SW仅缓存/assets/路径下的资源。

方案3:强制MSW注册优先级

启动MSW时指定立即注册策略,确保其先激活:

await worker.start({
  onUnhandledRequest: 'warn',
  serviceWorker: {
    options: {
      registrationStrategy: 'registerImmediately'
    }
  }
})
// 再注册PWA SW

四、验证步骤

  1. 打开浏览器开发者工具Application > Service Workers,确认两个Worker均已注册并激活。
  2. 在Network面板查看请求的Initiator是否为ServiceWorker,确认MSW已拦截请求。
  3. 查看MSW控制台日志,确认请求已匹配到对应处理器。

内容的提问来源于stack exchange,提问作者Leff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:30:32