5.7 KiB
5.7 KiB
Service Worker PostMessage 日志记录优化
问题描述
之前的实现中,PostMessage 日志记录虽然有 debugModeEnabled 开关,但在以下场景中仍然会对应用性能产生影响:
- 主线程消息发送时的日志记录:即使调试模式未启用,仍然会调用
logSentMessage()函数进行日志记录 - 消息日志存储和处理:日志数组会不断增长(最多 500 条),占用内存
- 调试面板关闭后的残留:从启用调试到禁用调试的过程中,日志没有被及时清空
解决方案
1. 完全由调试模式控制日志记录
在 postmessage-logger.ts 中实现以下改进:
// 内部检查函数
function isDebugModeActive(): boolean {
return debugModeEnabled;
}
// 改进的调试模式设置
export function setPostMessageLoggerDebugMode(enabled: boolean): void {
const wasEnabled = debugModeEnabled;
debugModeEnabled = enabled;
if (!enabled && wasEnabled) {
// 从启用变为禁用时,立即清空日志,释放内存
logs.length = 0;
pendingRequests.clear();
logIdCounter = 0;
}
}
// 改进的消息过滤
function shouldLogMessage(messageType: string): boolean {
// 调试模式未启用时,立即返回 false,不进行任何记录操作
if (!isDebugModeActive()) {
return false;
}
return !EXCLUDED_MESSAGE_TYPES.includes(messageType);
}
2. 在 Message Bus 中添加调试模式检查
在 message-bus.ts 中,在调用 logSentMessage() 前检查调试模式:
import { isPostMessageLoggerDebugMode } from '../postmessage-logger';
export function sendToClient(client: Client, message: unknown): void {
// ...
// Only attempt to log if debug mode is enabled
let logId = '';
if (isPostMessageLoggerDebugMode()) {
const messageType = (message as { type?: string })?.type || 'unknown';
logId = logSentMessage(messageType, message, client.id);
}
// ...
}
3. 在 Service Worker 中同步日志控制
在 sw/index.ts 中,确保接收消息时也受到调试模式的控制:
// Handle messages from main thread
sw.addEventListener('message', (event: ExtendableMessageEvent) => {
const messageType = event.data?.type || 'unknown';
const clientId = (event.source as Client)?.id || '';
// Log received message only if debug mode is enabled
let logId = '';
if (isPostMessageLoggerDebugMode()) {
logId = logReceivedMessage(messageType, event.data, clientId);
if (logId && debugModeEnabled) {
const logs = getAllPostMessageLogs();
const entry = logs.find(l => l.id === logId);
if (entry) {
broadcastPostMessageLog(entry);
}
}
}
// ... rest of the handler
});
性能影响
调试模式关闭时
- 零日志记录开销:不调用任何日志记录函数
- 零内存占用:日志数组为空
- 零性能影响:应用运行不受影响
调试模式启用时
- 完整的日志记录:所有 PostMessage 都被记录
- 实时日志广播:日志实时显示在调试面板
- 可接受的性能开销:仅在调试时产生
调试面板使用
启用调试模式
- 打开
http://localhost:7200/sw-debug.html - 点击 "启用调试" 按钮
- 切换到 "PostMessage 日志" 标签
- 查看所有主线程与 Service Worker 之间的消息通信
自动清理
当调试模式禁用时,日志会自动清空以释放内存。
实现细节
关键导出函数
| 函数 | 模块 | 作用 |
|---|---|---|
setPostMessageLoggerDebugMode(enabled) |
postmessage-logger.ts |
设置调试模式 |
isPostMessageLoggerDebugMode() |
postmessage-logger.ts |
检查调试模式是否启用 |
logReceivedMessage() |
postmessage-logger.ts |
记录接收的消息(需先检查调试模式) |
logSentMessage() |
postmessage-logger.ts |
记录发送的消息(需先检查调试模式) |
setDebugMode(enabled) |
message-bus.ts |
配置整个消息总线的调试模式 |
日志流程
启用调试模式
↓
setMessageSenderDebugMode(true)
↓
setDebugMode(true) in message-bus.ts
↓
setPostMessageLoggerDebugMode(true)
↓
所有 postMessage 都被记录到调试面板
↓
禁用调试模式
↓
setPostMessageLoggerDebugMode(false)
↓
日志数组立即清空,内存释放
修改的文件
-
apps/web/src/sw/task-queue/postmessage-logger.ts
- 添加
isDebugModeActive()内部函数 - 改进
setPostMessageLoggerDebugMode()逻辑 - 改进
shouldLogMessage()函数
- 添加
-
apps/web/src/sw/task-queue/utils/message-bus.ts
- 导入
isPostMessageLoggerDebugMode - 在
sendToClient()中添加调试模式检查 - 在
broadcastToAllClients()中添加调试模式检查
- 导入
-
apps/web/src/sw/index.ts
- 导入
isPostMessageLoggerDebugMode - 在消息处理器中添加调试模式检查
- 导入
-
apps/web/public/sw-debug.html
- 更新 PostMessage 日志标签的提示信息
- 更新控制台日志标签的提示信息
测试步骤
-
应用不开启调试时
- 正常使用应用
- 性能不受影响
-
启用调试模式
- 打开调试面板
- 启用调试
- 切换到 PostMessage 日志标签
- 执行应用操作
- 观察日志实时显示
-
禁用调试模式
- 点击"禁用调试"
- 检查日志是否清空
- 确认内存释放
向后兼容性
所有改动都是向后兼容的:
- 现有的调试面板功能完全保留
- 调试模式的启用/禁用逻辑不变
- 只是改进了性能特性
相关文件
/apps/web/public/sw-debug.html- 调试面板界面/apps/web/public/sw-debug/app.js- 调试面板应用逻辑/apps/web/src/sw/index.ts- Service Worker 入口