docs(phase3): add core optimization implementation plan

- Track A: Chat virtual scrolling with react-window
- Track B: Hands Web Worker isolation for security
- Track C: Intelligence caching (already completed)

Plan includes:
- File structure and task breakdown
- Code examples for each component
- Verification checklist
- Integration requirements

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-21 20:03:13 +08:00
parent 32b9b41144
commit 35b06f2e4a

View File

@@ -0,0 +1,397 @@
# ZCLAW 架构优化 - Phase 3: 核心优化 实施计划
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 实现核心性能优化 - 虚拟滚动、Web Worker 隔离、缓存策略
**Architecture:** 三条并行轨道,可独立实施和验证
**Tech Stack:** React, react-window, Web Worker, Valtio
**Spec Reference:** `docs/superpowers/specs/2026-03-21-architecture-optimization-design.md`
**Duration:** 6 周 (24 人日)
---
## 并行轨道概览
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Phase 3: 核心优化 (并行) │
├─────────────────────┬─────────────────────┬─────────────────────────────┤
│ Track A: Chat │ Track B: Hands │ Track C: Intelligence │
│ 虚拟滚动优化 │ Web Worker 隔离 │ 缓存策略 ✅ │
├─────────────────────┼─────────────────────┼─────────────────────────────┤
│ • react-window │ • browser-worker.ts │ • IntelligenceCache │
│ • 消息分页 │ • worker-pool.ts │ • TTL + LRU │
│ • 惰性加载 │ • 安全执行隔离 │ • 命中率统计 │
│ • 首屏 3x 提升 │ • XSS 防护 │ • 70% 响应提升 │
└─────────────────────┴─────────────────────┴─────────────────────────────┘
```
**Track C (Intelligence 缓存) 已在 Phase 2.5 完成**
---
## Track A: Chat 虚拟滚动优化
### 目标
| 指标 | 当前 | 目标 |
|------|------|------|
| 首屏渲染 | ~2s | <500ms |
| 1000+ 消息滚动 | 卡顿 | 60fps |
| 内存占用 | 无限增长 | 限制 100 |
### 文件结构
```
desktop/src/
├── components/ChatArea/
│ ├── MessageList.tsx # 修改: 使用虚拟滚动
│ ├── VirtualMessageList.tsx # 新建: react-window 封装
│ └── MessageItem.tsx # 新建: 单条消息组件
└── domains/chat/
└── hooks.ts # 修改: 添加分页 hooks
```
### Task A.1: 安装 react-window
**Files:**
- Modify: `desktop/package.json`
- [ ] **Step 1: 安装依赖**
```bash
cd g:/ZClaw_openfang/desktop && pnpm add react-window @types/react-window
```
- [ ] **Step 2: 验证安装**
```bash
pnpm list react-window
```
---
### Task A.2: 创建 VirtualMessageList 组件
**Files:**
- Create: `desktop/src/components/ChatArea/VirtualMessageList.tsx`
- Create: `desktop/src/components/ChatArea/MessageItem.tsx`
- [ ] **Step 1: 创建 MessageItem 组件**
```typescript
// desktop/src/components/ChatArea/MessageItem.tsx
import { memo } from 'react';
import type { Message } from '@/domains/chat';
interface MessageItemProps {
message: Message;
style?: React.CSSProperties;
}
export const MessageItem = memo(function MessageItem({ message, style }: MessageItemProps) {
return (
<div style={style} className={`message message-${message.role}`}>
<div className="message-content">{message.content}</div>
{message.streaming && <span className="streaming-indicator">...</span>}
</div>
);
});
```
- [ ] **Step 2: 创建 VirtualMessageList 组件**
```typescript
// desktop/src/components/ChatArea/VirtualMessageList.tsx
import { useRef, useCallback, useEffect } from 'react';
import { FixedSizeList as List } from 'react-window';
import { MessageItem } from './MessageItem';
import type { Message } from '@/domains/chat';
interface VirtualMessageListProps {
messages: Message[];
height: number;
width: number;
onScrollToEnd?: () => void;
}
export function VirtualMessageList({
messages,
height,
width,
onScrollToEnd,
}: VirtualMessageListProps) {
const listRef = useRef<List>(null);
// Auto-scroll to bottom when new message arrives
useEffect(() => {
if (listRef.current && messages.length > 0) {
listRef.current.scrollToItem(messages.length - 1, 'end');
}
}, [messages.length]);
const Row = useCallback(
({ index, style }: { index: number; style: React.CSSProperties }) => (
<MessageItem message={messages[index]} style={style} />
),
[messages]
);
return (
<List
ref={listRef}
height={height}
width={width}
itemCount={messages.length}
itemSize={80} // Approximate message height
overscanCount={5}
>
{Row}
</List>
);
}
```
---
### Task A.3: 更新 MessageList 使用虚拟滚动
**Files:**
- Modify: `desktop/src/components/ChatArea/MessageList.tsx`
- [ ] **Step 1: 替换实现**
将现有的全量渲染替换为 VirtualMessageList
---
### Task A.4: 添加消息分页支持
**Files:**
- Modify: `desktop/src/domains/chat/store.ts`
- Modify: `desktop/src/domains/chat/hooks.ts`
- [ ] **Step 1: 添加分页状态**
chatStore 中添加:
```typescript
pageSize: 50,
currentPage: 0,
hasMore: true,
loadMoreMessages: async () => { /* ... */ },
```
---
## Track B: Hands Web Worker 隔离
### 目标
| 指标 | 当前 | 目标 |
|------|------|------|
| 执行安全性 | eval() XSS 风险 | 完全隔离 |
| 错误隔离 | 主线程崩溃 | Worker 隔离 |
| 超时控制 | | 30s 强制终止 |
### 文件结构
```
desktop/src/
├── workers/
│ ├── browser-worker.ts # 新建: 浏览器执行 Worker
│ └── worker-pool.ts # 新建: Worker 池管理
├── lib/
│ └── browser-executor.ts # 修改: 使用 Worker
└── domains/hands/
└── store.ts # 修改: 集成 Worker 执行
```
### Task B.1: 创建 Browser Worker
**Files:**
- Create: `desktop/src/workers/browser-worker.ts`
- [ ] **Step 1: 创建 Worker 脚本**
```typescript
// desktop/src/workers/browser-worker.ts
/// <reference lib="webworker" />
const ctx = self as DedicatedWorkerGlobalScope;
interface ExecuteRequest {
type: 'execute';
id: string;
script: string;
args: unknown[];
timeout: number;
}
interface ExecuteResponse {
type: 'result' | 'error';
id: string;
result?: unknown;
error?: string;
}
ctx.onmessage = async (e: MessageEvent<ExecuteRequest>) => {
const { type, id, script, args, timeout } = e.data;
if (type !== 'execute') return;
const timeoutId = setTimeout(() => {
ctx.postMessage({
type: 'error',
id,
error: 'Execution timeout',
} as ExecuteResponse);
}, timeout);
try {
// Safe execution without DOM access
const fn = new Function('args', script);
const result = await fn(args);
clearTimeout(timeoutId);
ctx.postMessage({ type: 'result', id, result } as ExecuteResponse);
} catch (err) {
clearTimeout(timeoutId);
ctx.postMessage({
type: 'error',
id,
error: err instanceof Error ? err.message : String(err),
} as ExecuteResponse);
}
};
ctx.postMessage({ type: 'ready' });
```
---
### Task B.2: 创建 Worker Pool
**Files:**
- Create: `desktop/src/workers/worker-pool.ts`
- [ ] **Step 1: 创建 Worker 池**
```typescript
// desktop/src/workers/worker-pool.ts
export class BrowserWorkerPool {
private workers: Worker[] = [];
private available: Worker[] = [];
private maxWorkers: number;
constructor(maxWorkers = 4) {
this.maxWorkers = maxWorkers;
}
private createWorker(): Worker {
return new Worker(
new URL('./browser-worker.ts', import.meta.url),
{ type: 'module' }
);
}
async execute(script: string, args: unknown[], timeout = 30000): Promise<unknown> {
const worker = this.available.pop() || this.createWorker();
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
worker.terminate();
reject(new Error('Execution timeout'));
}, timeout);
const handler = (e: MessageEvent) => {
if (e.data.type === 'result') {
clearTimeout(timeoutId);
worker.removeEventListener('message', handler);
this.available.push(worker);
resolve(e.data.result);
} else if (e.data.type === 'error') {
clearTimeout(timeoutId);
worker.removeEventListener('message', handler);
this.available.push(worker);
reject(new Error(e.data.error));
}
};
worker.addEventListener('message', handler);
worker.postMessage({
type: 'execute',
id: Date.now().toString(),
script,
args,
timeout,
});
});
}
terminateAll(): void {
this.workers.forEach(w => w.terminate());
this.workers = [];
this.available = [];
}
}
export const browserWorkerPool = new BrowserWorkerPool();
```
---
### Task B.3: 集成到 Hands Domain
**Files:**
- Modify: `desktop/src/domains/hands/store.ts`
- [ ] **Step 1: 使用 Worker 执行**
`triggerHand` action 中使用 `browserWorkerPool.execute()` 替代直接 `eval()`
---
## Track C: Intelligence 缓存策略 ✅ 已完成
已在 Phase 2.5 实现:
- `desktop/src/domains/intelligence/cache.ts` - LRU + TTL 缓存
- `desktop/src/domains/intelligence/store.ts` - 带缓存的 Valtio store
- `desktop/src/domains/intelligence/hooks.ts` - React hooks
---
## 验证清单
### Track A 验证
- [ ] 首屏渲染 < 500ms
- [ ] 1000+ 消息滚动 60fps
- [ ] 消息正确显示
- [ ] 流式消息正常更新
### Track B 验证
- [ ] Worker 正常创建和销毁
- [ ] 超时正确终止
- [ ] 错误正确隔离
- [ ] XSS 攻击被阻止
### 集成验证
- [ ] 所有 TypeScript 编译通过
- [ ] 现有测试通过
- [ ] E2E 核心流程正常
---
## 提交规范
```
feat(chat): add virtual scrolling with react-window
feat(hands): add Web Worker isolation for browser execution
perf(intelligence): add LRU cache with TTL support
```