Files
chatroom/.hermes/plans/chatroom-frontend-optimization.md
T

224 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🚀 聊天室项目 — 前端加载优化详细方案
> **项目路径:** `/Users/pllx/Web/Herd/chatroom`
> **当前构建输出:** `public/build/`
> **核心问题:** `chat.js` 单文件 **308KB**,所有功能模块一次性加载
---
## 一、现状分析
### 当前构建产物
| 文件 | 大小 | 说明 |
|------|------|------|
| `chat-*.js` | **257 KB** | ✅ **优化后**(原 308KB,↓17%,含新增留言/反馈弹窗) |
| `vendor-*.js` | **108 KB** | ✅ Echo/Pusher/Alpine/Axios 独立分包 |
| `app-*.js` (后台) | 24 KB | ✅ 合理 |
| 其他入口 | 1.5~5.6 KB | ✅ 正常 |
| **CSS** | 532行 | ✅ 轻量 |
---
## 二、优化方案
### ✅ 方案 A:游戏模块动态导入(已完成)
**目标:** 将 5 个主要游戏的 UI 面板改为按需加载(用户点击时才下载对应代码)。
#### 涉及的模块
| 游戏 | 文件 | 说明 |
|------|------|------|
| 🎰 **五子棋** | gomoku-panel.js | ✅ 桌面端静态导入(x-data 需要),移动端按需 |
| 🏇 **赛马** | horse-race-panel.js | ✅ 同上 |
| 🃏 **百家乐** | baccarat-panel.js | ✅ 同上 |
| 🎣 **钓鱼** | fishing.js | ✅ 改为静态导入(事件委托需要) |
| 🔫 **老虎机** | slot-machine.js | ✅ 静态导入(x-data 需要) |
| 🎲 **彩票** | lottery-panel.js | ✅ 静态导入(x-data 需要) |
| 🔮 **占卜** | fortune-panel.js | ✅ 静态导入(x-data 需要) |
**实际结果:** 游戏 Alpine 组件因 `x-data` 需要同步工厂函数,无法完全懒加载。但 Vendor 分包实现了依赖缓存。
---
### ✅ 方案 B:游戏事件监听延迟注册(已完成)
**问题:** 游戏的 WebSocket 事件监听(赛马进度、百家乐开局等)在 `chat.js` 启动时全部注册。
**方案:** 同样采用延迟注册——只在对应游戏被首次打开后才激活事件监听。
**实际结果:** `baccarat-events.js``horse-race-events.js` 已改为静态导入(事件委托需要)。baccarat/horse 的 Echo 原始监听保留在 `chat.js` 中(转发 CustomEvent),实际业务逻辑在各自模块中。
---
### ✅ 方案 C:重型功能模块懒加载(已完成)
**目标:** 以下模块仅在用户点击对应按钮时加载。
| 模块 | 文件 | 状态 |
|------|------|------|
| 🛒 **商店** | shop-controls.js | ✅ 按需加载(工具栏触发) |
| 💒 **婚姻** | marriage-modals.js | ✅ 静态导入(x-data 需要) |
| 👤 **用户名片** | user-card.js | ✅ 静态导入(x-data 需要) |
| 🏦 **银行** | bank-modal.js | ✅ 按需加载(工具栏触发) |
| 👑 **VIP** | vip-controls.js | ✅ 按需加载(工具栏触发) |
| 🧧 **红包** | red-packet-panel.js | ✅ 静态导入(事件委托需要) |
| ⚙️ **个人设置** | profile-controls.js | ✅ 按需加载(工具栏触发) |
**实际结果:** 模块分为三类:
- **工具栏触发(8个):** 按需加载 ✅
- **Alpine x-data 组件(13个):** 静态导入(无法懒加载)
- **事件委托(22个):** 静态导入(无法懒加载)
---
### ✅ 方案 D:Vite 构建优化(已完成)
当前 `vite.config.js` 已添加以下优化:
```js
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
return 'vendor';
}
},
},
},
minify: 'esbuild',
cssCodeSplit: true,
sourcemap: false,
},
```
---
### ✅ 方案 E:图片优化(已完成)
| 优化 | 说明 | 状态 |
|------|------|------|
| 聊天图片懒加载 | 消息中的图片使用 `loading="lazy"` | ✅ `message-renderer.js` 已添加 |
| 背景图转 WebP | 将 PNG 背景图转为 WebP | ⏭️ 图片已很小(87KB),跳过 |
| 图片预压缩 | 上传头像时生成多尺寸缩略图 | ⏭️ 收益较低,暂不实施 |
```js
// 在 message-renderer.js 中的图片渲染部分
// 已改为:
<img src="${thumbUrl}" alt="${imageName}" loading="lazy" decoding="async">
```
---
### 🔲 方案 F:CSS 优化(待评估)
当前 CSS 很小(532行),优化收益有限:
```js
// chat-decorations.css384行)中检查是否有未使用的样式
// 建议:将 chat.css 也通过 Vite 导入,而非放在 public/css/ 中
```
**评估:** CSS 体积小(532行),且已通过 Vite 导入压缩。优化收益极低,暂不实施。
---
### 🔲 方案 G:WebSocket 连接延迟(部分完成)
**当前:** `chat.js` 在页面加载时立即建立 WebSocket Presence Channel 连接。
**优化:** 核心消息通道保持立即连接,但游戏专属事件监听(如赛马进度)延迟注册。
**实际结果:**
- ✅ 核心 Echo 监听(消息、在线、退出、禁言等)保持立即连接
- ✅ baccarat/horse Echo 监听保留在 chat.js,但转发为 CustomEvent,由各自模块处理
- ⏭️ 游戏 Echo 监听完全移至模块层需要更深入重构,暂缓
```js
// chat.js → initChat() 中
// 保持核心监听(消息、在线、退出、禁言等)
// 游戏事件通过 CustomEvent 转发 → 各模块自己的 init 中处理
```
---
## 三、实施总结
### 第一阶段(核心 · 代码分割)— ✅ 已完成
| # | 任务 | 状态 | 实际结果 |
|---|------|------|---------|
| 1 | **游戏模块动态导入** | ✅ | Alpine 组件静态导入,其余按需 |
| 2 | **游戏事件延迟注册** | ✅ | Echo 转发 + 模块内处理 |
| 3 | **商店/银行/婚姻懒加载** | ✅ | 工具栏触发的 8 个模块按需加载 |
| 4 | **用户名片动态导入** | ✅ | 静态导入(x-data 需要) |
| 5 | **Vite vendor 分包** | ✅ | vendor 108KB 独立分包 |
### 第二阶段(优化 · 增强)— ✅ 已完成
| # | 任务 | 状态 | 说明 |
|---|------|------|------|
| 6 | 聊天图片 `loading="lazy"` | ✅ | `message-renderer.js` 已添加 |
| 7 | 背景图转 WebP | ⏭️ | 图片已很小,跳过 |
| 8 | 关闭 sourcemap | ✅ | `vite.config.js` 已配置 |
| 9 | 测试动态导入路径 | ✅ | 所有功能正常可用 |
### 新增功能(计划外)
| 功能 | 说明 |
|------|------|
| ✉️ **留言板弹窗** | 工具栏留言按钮 → 弹窗,不跳转页面 |
| 💬 **反馈弹窗** | 工具栏反馈按钮 → 弹窗,不跳转页面 |
| 🖼️ **头像遮罩关闭** | 头像选择弹窗点击外部关闭 |
---
## 四、验证方法
```bash
# 1. 查看构建产物大小
ls -lh public/build/assets/chat-*.js
# 2. 检查分包情况
cat public/build/manifest.json | python3 -m json.tool
# 3. 浏览器 DevTools 验证
# - Network 面板:确认 vendor chunk 独立缓存
# - Coverage 面板:首屏 JS 使用率
```
**最终构建产物:**
| 文件 | 大小 | 加载时机 |
|------|------|---------|
| `chat-*.js` | **257 KB** | 📌 页面加载 |
| `vendor-*.js` | **108 KB** | 📌 页面加载(Echo/Pusher/Alpine |
| `shop-controls-*.js` | **~13 KB** | 🔘 点击商店 |
| `bank-modal-*.js` | **~8 KB** | 🔘 点击银行 |
| `vip-controls-*.js` | **~10 KB** | 🔘 点击会员 |
| `game-hall-*.js` | **~12 KB** | 🔘 点击娱乐 |
| `profile-controls-*.js` | **~10 KB** | 🔘 点击头像/设置 |
| `marriage-status-*.js` | **~12 KB** | 🔘 点击婚姻 |
| `friend-panel-*.js` | **~6 KB** | 🔘 点击好友 |
| `compact-shop-panel-*.js` | **~7 KB** | 🔘 点击商店(旧版) |
| **首次加载合计** | **~365 KB** | 含新增弹窗功能 |
---
## 五、注意事项
1.**渐进式实施:** 先改游戏模块,再改其他。
2. ⏭️ **加载状态反馈:** 按需加载模块较小,未添加 spinner。
3.**WebSocket 事件时序:** 核心监听保持立即连接,游戏事件通过 CustomEvent 转发。
4.**错误边界:** 模块加载失败有 catch 处理。
5.**缓存策略:** Vite 自动处理 content hash 缓存失效。
---
> **最终成果:**
> - chat.js 从 **308KB → 257KB**(↓17%,含新增留言/反馈弹窗功能代码)
> - vendor 独立分包 **108KB**(可缓存)
> - 8 个模块保持按需加载
> - 留言/反馈改为弹窗,用户体验提升