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的警告信息,确认请求未匹配的原因。
解决步骤
修正请求匹配规则
如果axios配置了baseURL(如axios.defaults.baseURL = '/api'),需将MSW处理器路径改为对应前缀,比如rest.post('/api/login', ...),或在开发环境临时移除baseURL配置。调整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>, ) }移除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仅缓存静态资源:
- 修改
registerSW.js:if('serviceWorker' in navigator) { navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/assets/', type: 'classic' }) } - 调整Vite PWA插件配置,让PWA SW仅缓存
/assets/路径下的资源。
方案3:强制MSW注册优先级
启动MSW时指定立即注册策略,确保其先激活:
await worker.start({ onUnhandledRequest: 'warn', serviceWorker: { options: { registrationStrategy: 'registerImmediately' } } }) // 再注册PWA SW
四、验证步骤
- 打开浏览器开发者工具
Application > Service Workers,确认两个Worker均已注册并激活。 - 在
Network面板查看请求的Initiator是否为ServiceWorker,确认MSW已拦截请求。 - 查看MSW控制台日志,确认请求已匹配到对应处理器。
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

