feat: 升级至 v0.3.11 — 流式输出性能优化 12 项,解决长内容卡死
针对 AI 流式输出长内容时应用卡死问题,实施 12 项性能优化: 渲染层优化(F1/F3/F7): - F1: React.memo 包裹 MessageItem/AssistantMessage,跳过历史消息重渲染 - F3: 流式时用纯文本渲染,避免 ReactMarkdown 全量重解析 O(n²) - F7: useMemo 缓存 ReactMarkdown 元素,非流式时复用实例 滚动与布局(F2/F4/F10/F12): - F2: 滚动节流 rAF + 100ms throttle + trailing 兜底,避免高频布局 - F4: CSS content-visibility 准虚拟滚动,跳过不可见区域布局 - F10: CSS contain 隔离 markdown 布局计算 - F12: 滚动容器 transform: translateZ(0) GPU 加速 状态与 IPC 批处理(F5/F8/F9): - F5: 渲染进程 text_delta rAF 批处理,合并多次 store 写入 - F8: 主进程 text_delta 32ms 节流合并,降低 IPC 频率 - F9: reasoning_delta traceSteps thought 走 rAF 批处理 代码清理(F11): - F11: 移除 rehypeRaw,节省 raw HTML 解析开销 + 防 AI 输出注入 验证:tsc --noEmit 通过,flush 逻辑在 done/error/cleanup 三处正确执行。
This commit is contained in:
@@ -2,8 +2,13 @@
|
||||
* MessageItem — 单条消息路由组件
|
||||
*
|
||||
* 根据消息 role 路由到对应的子组件渲染。
|
||||
*
|
||||
* F1 性能优化: 使用 React.memo 包裹,避免流式 delta 触发历史消息重渲染。
|
||||
* 浅比较策略:message 引用变化(store 仅替换最后一条)或 isStreaming 变化时才重渲染。
|
||||
* 历史消息的 message 引用在 delta 流中保持不变,因此可跳过 re-render。
|
||||
*/
|
||||
|
||||
import { memo } from 'react';
|
||||
import { Box, Typography, Stack } from '@mui/material';
|
||||
import { Terminal } from 'lucide-react';
|
||||
import type { ChatMessage } from '@renderer/stores/agent-store';
|
||||
@@ -18,7 +23,7 @@ interface MessageItemProps {
|
||||
isStreaming?: boolean;
|
||||
}
|
||||
|
||||
export function MessageItem({ message, isLast, isStreaming }: MessageItemProps): React.JSX.Element {
|
||||
function MessageItemImpl({ message, isLast, isStreaming }: MessageItemProps): React.JSX.Element {
|
||||
switch (message.role) {
|
||||
case 'user':
|
||||
return <UserMessage message={message} />;
|
||||
@@ -41,6 +46,14 @@ export function MessageItem({ message, isLast, isStreaming }: MessageItemProps):
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* F1: memo 默认浅比较 props。
|
||||
* - message 是对象引用,store 更新最后一条时只替换最后一条,历史消息引用不变 → 跳过 re-render
|
||||
* - isStreaming 是 boolean,流式过程中值不变(持续 true),流结束才变化一次 → 历史消息仅重渲染一次
|
||||
* - isLast 是 boolean,仅在最后一条切换时变化
|
||||
*/
|
||||
export const MessageItem = memo(MessageItemImpl);
|
||||
|
||||
/** ToolMessage — 独立的工具结果消息(role=tool) */
|
||||
function ToolMessage({ message }: { message: ChatMessage }): React.JSX.Element {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user