T40 UI 审计修复(60 页面全覆盖): - 新增 $acc-d/$wrn-d 渐变中间色变量,修复首页轮播渐变硬编码 - 替换 8 处裸 white 为 $white 设计变量(5 个 SCSS 文件) - 修复 7 处触摸目标 40/44px → 48px(健康/消息/咨询/预约/首页) - 3 页面新增 Loading 状态(体征录入/个人中心/就诊人添加) - statusTag 移除硬编码布局值,改用 SCSS mixin 控制 - 医生端 14 页面架构 Hook 层补充(useThrottledDidShow 替换 useEffect) - 移除 action-inbox 未使用 import 安全 P0 修复: - JWT 中间件加固:token 类型校验 + 过期预检 + 类型别名简化 - 速率限制增强:滑动窗口 + 暴力破解防护 - analytics handler 错误处理完善 文档: - T40 审计报告(24 PASS / 36 PASS_WITH_ISSUES / 0 NEEDS_WORK) - 5 份 DevTools/性能审计讨论记录 - wiki 症状导航 + 小程序章节更新
123 lines
6.1 KiB
Markdown
123 lines
6.1 KiB
Markdown
# DevTools 卡死根因分析 — 四专家组深度诊断
|
||
|
||
> 日期: 2026-05-14 | 参与者: 内存泄漏专家 + 渲染性能专家 + 网络/API专家 + DevTools环境专家
|
||
|
||
## 背景
|
||
|
||
微信开发者工具中 HMS 小程序持续卡死:
|
||
- 内存从 1283MB 增长到 2290MB+
|
||
- 截图功能始终超时(mp.screenshot timeout)
|
||
- 页面导航 30s 超时
|
||
- 修复 analytics/batch 422 + auth restore 后,卡死依旧
|
||
|
||
## 根因链条(四维度交叉验证)
|
||
|
||
```
|
||
DevTools 环境问题(基线内存偏高)
|
||
├─ compileHotReLoad=true → 每次文件变化重建编译上下文,旧上下文不释放
|
||
├─ minified=true → DevTools 二次压缩 JS,每个刷新周期重复执行
|
||
└─ prebundle=false → webpack 内存中维护完整依赖图
|
||
↓
|
||
内存基线已高 → GC 频率升高 → JS 线程长时间占用
|
||
↓
|
||
网络/API 循环(持续加压)
|
||
├─ Redis 不可用 → 限流中间件每请求 2 次 error 日志(日志洪泛)
|
||
├─ JWT 中间件每请求 2 次 DB 查询(无缓存)
|
||
├─ 首页 Tab 切换并发 6+ 请求 × 2 次 DB = 12-16 次 DB 查询
|
||
└─ 咨询长轮询 401 时 token 刷新 + 重试循环
|
||
↓
|
||
后端压力大 + 前端请求队列积压
|
||
↓
|
||
内存泄漏(持续增长)
|
||
├─ consultation detail messages 数组无上限(只增不减)
|
||
├─ request.ts inflightRequests 无超时清理
|
||
├─ TrendChart canvas node 卸载后未释放
|
||
└─ BLE DataBuffer seenKeys Set 不随数据淘汰清理
|
||
↓
|
||
内存突破阈值 → GC 暂停 → automator 超时 → 卡死
|
||
```
|
||
|
||
## CRITICAL 问题(共 7 项)
|
||
|
||
### 1. consultation detail messages 数组无上限
|
||
- **文件:** `pages/consultation/detail/index.tsx:70-76`(患者端 + 医生端相同)
|
||
- **问题:** 长轮询每 3 秒 `[...prev, ...fresh]` 拼接,React state 和 messagesRef 各持一份,无上限
|
||
- **影响:** 长时间聊天 5000+ 条 → 5MB+ 双份 → 10MB+
|
||
|
||
### 2. compileHotReLoad 配置矛盾
|
||
- **文件:** `project.config.json:10` vs `project.private.config.json:16`
|
||
- **问题:** public 设 false,private 覆盖为 true → 热重载开启 → 编译上下文累积
|
||
- **影响:** 这是 DevTools 内存增长的最主要贡献者
|
||
|
||
### 3. minified=true 开发模式多余压缩
|
||
- **文件:** `project.config.json:12`
|
||
- **问题:** DevTools 层二次压缩 JS,每个刷新周期重复执行
|
||
- **影响:** 72 个 JS 文件 × 每次刷新重新压缩
|
||
|
||
### 4. Redis 不可用 → 限流日志洪泛
|
||
- **文件:** `crates/erp-server/src/middleware/rate_limit.rs:108,119`
|
||
- **问题:** 每个受保护请求 2 次 Redis 连接尝试失败 → 2 条 error 日志
|
||
- **影响:** 50 req/s = 100 条/秒 error 日志
|
||
|
||
### 5. JWT 中间件每请求 2 次 DB 查询无缓存
|
||
- **文件:** `crates/erp-auth/src/middleware/jwt_auth.rs:68-77`
|
||
- **问题:** fetch_user_department_ids + fetch_permission_data_scopes,同一用户每请求都查
|
||
- **影响:** 6 并发请求 = 12 次 DB 查询
|
||
|
||
### 6. 咨询长轮询 Tab 切换后不停止
|
||
- **文件:** `pages/consultation/detail/index.tsx:61-88`
|
||
- **问题:** DevTools 页面生命周期与真机不同,useEffect cleanup 不一定触发
|
||
- **影响:** MCP 批量导航时多个轮询叠加
|
||
|
||
### 7. 健康数据页 14 useState 重渲染风暴
|
||
- **文件:** `pages/health/index.tsx`
|
||
- **问题:** 14 个 useState + useThrottledDidShow 触发连锁更新
|
||
- **影响:** Tab 切换时 React 调和开销大
|
||
|
||
## HIGH 问题(共 8 项)
|
||
|
||
| # | 问题 | 文件 | 影响 |
|
||
|---|------|------|------|
|
||
| H1 | request.ts inflightRequests 无超时清理 | services/request.ts:164 | 挂死请求闭包永久驻留 |
|
||
| H2 | TrendChart canvas node 卸载未释放 | components/TrendChart/index.tsx:153 | 每次 Tab 切换 1-5MB canvas 泄漏 |
|
||
| H3 | auth store module-level 缓存 logout 不清 | stores/auth.ts:9-14 | 多账户数据残留 |
|
||
| H4 | prebundle 禁用 webpack 内存膨胀 | config/dev.ts:6-8 | 大型 chunk 完整依赖图驻留内存 |
|
||
| H5 | 首页 6+ 并发 API 请求无优先级 | pages/index/index.tsx:194 | 后端压力叠加 |
|
||
| H6 | 长轮询 401 刷新重试循环 | services/request.ts:117-131 | reLaunch 异步期间继续请求 |
|
||
| H7 | BLE syncToServer 重试无退避 | services/ble/BLEManager.ts:262 | flush→失败→push back→flush 循环 |
|
||
| H8 | base.wxml 68KB 模板体积偏大 | dist/base.wxml | DevTools 解析负担 |
|
||
|
||
## 立即缓解措施(不改代码)
|
||
|
||
1. **关闭热重载:** DevTools 设置 → 关闭"文件保存时自动编译"
|
||
2. **关闭压缩:** project.config.json → `"minified": false`
|
||
3. **定期重启 DevTools:** 每 30 分钟或内存超过 1.5GB
|
||
4. **重启后端时配置 fail_close=false:** 避免 Redis 问题阻塞所有请求
|
||
|
||
## 修复优先级
|
||
|
||
| 优先级 | 修复项 | 预期效果 | 复杂度 |
|
||
|--------|--------|---------|--------|
|
||
| P0 | messages 数组加 MAX_STATE_MESSAGES=300 上限 | 消除最大内存泄漏源 | 低 |
|
||
| P0 | project.private.config.json compileHotReLoad=false | 降低 DevTools 内存基线 | 极低 |
|
||
| P0 | project.config.json minified=false | 消除多余压缩开销 | 极低 |
|
||
| P1 | 限流中间件缓存 Redis 连接失败状态(5s) | 消除日志洪泛 | 中 |
|
||
| P1 | JWT 中间件加 DashMap 缓存(TTL 60s) | 降低 DB 查询量 90% | 中 |
|
||
| P1 | 长轮询迁移到 useDidShow/useDidHide 管理 | 防止多实例轮询 | 中 |
|
||
| P2 | request.ts inflightRequests 加超时清理 | 防止闭包泄漏 | 低 |
|
||
| P2 | TrendChart useEffect 添加 cleanup | 释放 canvas 节点 | 低 |
|
||
| P2 | prebundle 启用(重新评估) | 降低 webpack 内存占用 | 低 |
|
||
| P3 | BLE DataBuffer seenKeys 同步清理 | 减少 Set 增长 | 低 |
|
||
| P3 | auth store logout 清除 module-level 缓存 | 多账户安全 | 极低 |
|
||
|
||
## 结论
|
||
|
||
DevTools 卡死是**多重因素叠加**的结果,不是单一 bug:
|
||
1. DevTools 环境配置(热重载+压缩)抬高了内存基线
|
||
2. 后端 Redis 不可用导致日志洪泛 + 无限流保护
|
||
3. 前端 consultation detail messages 无上限是最直接的内存泄漏
|
||
4. JWT 中间件无缓存导致后端 DB 压力放大
|
||
5. 长轮询生命周期管理在 DevTools 中行为异常
|
||
|
||
**P0 修复后预计内存增长速度降低 70%+,DevTools 可稳定运行 1 小时以上。**
|