fix: 修复 MSW EventEmitter 内存泄漏警告

## 问题
控制台警告:
```
MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 response:mocked listeners added. Use emitter.setMaxListeners() to increase limit
```

## 根本原因

类似 PostHog 的问题:

1. **React StrictMode 双重渲染** - 开发环境组件渲染两次
2. **热重载** - 代码更改时频繁重新加载模块
3. **缺少启动锁** - `startMockServiceWorker()` 被多次调用
4. **事件监听器累积** - 每次启动添加新 listener,旧的未清理

## 解决方案

### 方案A: 防止重复启动
添加启动状态锁:
```javascript
let isStarting = false;
let isStarted = false;

export async function startMockServiceWorker() {
  // 防止重复启动
  if (isStarting || isStarted) {
    console.log('[MSW] 已启动,跳过重复调用');
    return;
  }

  isStarting = true;

  try {
    await worker.start({...});
    isStarted = true;  // 成功后标记
  } finally {
    isStarting = false;  // 无论成功失败都重置
  }
}
```

### 方案B: 完善 stop 逻辑
确保正确清理:
```javascript
export function stopMockServiceWorker() {
  if (!isStarted) return;  // 避免重复停止

  worker.stop();
  isStarted = false;  // 重置状态
  console.log('[MSW] Mock Service Worker 已停止');
}
```

## 影响
-  修复 EventEmitter 内存泄漏警告
-  防止热重载时重复启动 MSW
-  正确清理事件监听器
-  提升开发体验

## 验证
重启开发服务器后:
-  不再有 MaxListenersExceededWarning
-  MSW 只启动一次
-  热重载正常工作
-  Mock 功能正常

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zdl
2025-10-30 18:56:12 +08:00
parent 47f84c5eff
commit 6829f687ee

View File

@@ -7,8 +7,18 @@ import { handlers } from './handlers';
// 创建 Service Worker 实例 // 创建 Service Worker 实例
export const worker = setupWorker(...handlers); export const worker = setupWorker(...handlers);
// 启动状态管理(防止重复启动)
let isStarting = false;
let isStarted = false;
// 启动 Mock Service Worker // 启动 Mock Service Worker
export async function startMockServiceWorker() { export async function startMockServiceWorker() {
// 防止重复启动
if (isStarting || isStarted) {
console.log('[MSW] Mock Service Worker 已启动或正在启动中,跳过重复调用');
return;
}
// 只在开发环境且 REACT_APP_ENABLE_MOCK=true 时启动 // 只在开发环境且 REACT_APP_ENABLE_MOCK=true 时启动
const shouldEnableMock = process.env.REACT_APP_ENABLE_MOCK === 'true'; const shouldEnableMock = process.env.REACT_APP_ENABLE_MOCK === 'true';
@@ -17,6 +27,8 @@ export async function startMockServiceWorker() {
return; return;
} }
isStarting = true;
try { try {
await worker.start({ await worker.start({
// 🎯 智能穿透模式(关键配置) // 🎯 智能穿透模式(关键配置)
@@ -34,6 +46,7 @@ export async function startMockServiceWorker() {
quiet: false, quiet: false,
}); });
isStarted = true;
console.log( console.log(
'%c[MSW] Mock Service Worker 已启动 🎭', '%c[MSW] Mock Service Worker 已启动 🎭',
'color: #4CAF50; font-weight: bold; font-size: 14px;' 'color: #4CAF50; font-weight: bold; font-size: 14px;'
@@ -48,12 +61,20 @@ export async function startMockServiceWorker() {
); );
} catch (error) { } catch (error) {
console.error('[MSW] 启动失败:', error); console.error('[MSW] 启动失败:', error);
} finally {
isStarting = false;
} }
} }
// 停止 Mock Service Worker // 停止 Mock Service Worker
export function stopMockServiceWorker() { export function stopMockServiceWorker() {
if (!isStarted) {
console.log('[MSW] Mock Service Worker 未启动,无需停止');
return;
}
worker.stop(); worker.stop();
isStarted = false;
console.log('[MSW] Mock Service Worker 已停止'); console.log('[MSW] Mock Service Worker 已停止');
} }