共计 1959 个字符,预计需要花费 5 分钟才能阅读完成。
问题背景
最近在开发类似 ChatGPT 的网页应用时,遇到了明显的性能问题。尤其是在长对话场景下,用户普遍反馈输入延迟和消息渲染卡顿。通过 Chrome DevTools 的 Performance 面板分析,发现以下几个关键问题点:

- WebSocket 连接在高延迟网络环境下会出现不稳定断开
- 长消息列表的渲染导致主线程阻塞
- 重复请求相同静态资源增加网络负担
技术方案
WebSocket 连接优化
为了确保稳定的实时通信连接,我们实现了以下优化措施:
- 心跳机制:定期发送 ping/pong 帧保持连接活跃
- 消息分块:将大消息拆分为多个 chunk 传输
- 智能重连:采用指数退避算法自动重连
前端渲染优化
针对 React 应用的特点,我们实施了这些优化:
- 全面使用 React.memo 减少不必要的重新渲染
- 实现虚拟列表技术处理长对话历史
- 优化 useEffect 依赖项避免过度执行
缓存策略
通过 Service Worker 我们建立了多级缓存:
- 静态资源缓存:CSS/JS/ 字体等长期缓存
- API 响应缓存:对频繁请求的 API 结果缓存
- 动态更新策略:通过版本控制管理缓存更新
代码实现
WebSocket 重连逻辑
class WSConnection {
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
private reconnectDelay = 1000;
connect() {this.socket = new WebSocket(URL);
this.socket.onclose = () => {if (this.reconnectAttempts < this.maxReconnectAttempts) {
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
30000 // 最大 30 秒
);
setTimeout(() => {
this.reconnectAttempts++;
this.connect();}, delay);
}
};
}
}
虚拟列表实现
import {FixedSizeList as List} from 'react-window';
const MessageList = ({messages}) => (
<List
height={600}
itemCount={messages.length}
itemSize={120}
width="100%"
>
{({index, style}) => (<div style={style}>
<MessageItem message={messages[index]} />
</div>
)}
</List>
);
Service Worker 缓存策略
// service-worker.js
const CACHE_NAME = 'v1';
const STATIC_FILES = ['/main.css', '/app.js'];
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(CACHE_NAME)
.then(cache => cache.addAll(STATIC_FILES))
);
});
self.addEventListener('fetch', (event) => {
event.respondWith(caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
性能对比
经过上述优化后,我们获得了显著的性能提升:
- Lighthouse 评分从 65 提升到 92
- 消息渲染时间从平均 450ms 降低到 120ms
- WebSocket 重连成功率从 70% 提高到 98%
避坑指南
在实际实施过程中,有几个常见问题需要注意:
- WebSocket 消息格式选择:
- JSON 易读但体积大
-
Protobuf 体积小但需要预定义 schema
-
虚拟列表滚动位置恢复:
- 需要保存滚动位置状态
-
动态内容高度需要特殊处理
-
缓存失效策略:
- 避免缓存过期的 API 响应
- 使用 Cache API 的版本控制
延伸思考
对于追求极致性能的团队,还可以考虑以下方向:
- 实现 AB 测试框架验证不同优化策略的效果
- 评估 SSE(Server-Sent Events) 在特定场景下的替代方案
- 探索 WebAssembly 加速消息解析
架构示意图
graph TD
A[客户端] -->|WebSocket| B(消息网关)
B --> C[消息服务]
B --> D[会话服务]
C --> E[(消息存储)]
D --> F[(会话存储)]
进阶优化方向
- 实现 Web Worker 处理消息解析和预处理
- 采用 HTTP/2 Server Push 预加载关键资源
- 实验性尝试 WebTransport 协议替代 WebSocket
正文完
