From f4373c098e33fa41a2ab849658c00988a2ba97ab Mon Sep 17 00:00:00 2001 From: butubb <1422726308@qq.com> Date: Sun, 11 Oct 2026 08:16:41 +0800 Subject: [PATCH] =?UTF-8?q?perf(console):=20=E6=97=A5=E5=BF=97=E8=A1=8C?= =?UTF-8?q?=E5=8A=A0=20memo=20=E2=80=94=E2=80=94=20=E7=82=B9=E6=8A=98?= =?UTF-8?q?=E5=8F=A0=E5=8D=A1=E6=AD=BB=E5=B0=B1=E6=98=AF=E8=BF=99=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 日志是「来一条 push 一条」,store 里的数组每来一条就是新的,于是整个列表重渲染; 而列表最多留 500 条,不做 memo 就是每来一行重渲染 500 行,每行还要跑 5 次 cn() (tailwind-merge 不便宜)。爬虫一跑日志是成片来的,主线程直接被占满 —— 表现就是 点什么都没反应,点折叠最容易注意到,因为那一下还要把整份列表挂载/卸载一遍。 log 对象在数组里是稳定引用,memo 之后只有新来的那一行会渲染。 --- webui/src/components/console/TerminalLine.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/webui/src/components/console/TerminalLine.tsx b/webui/src/components/console/TerminalLine.tsx index 8084a24..e512fcc 100644 --- a/webui/src/components/console/TerminalLine.tsx +++ b/webui/src/components/console/TerminalLine.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react' + import { cn } from '@/lib/utils' import type { LogEntry } from '@/types/crawler' @@ -41,7 +43,18 @@ const levelIcons: Record = { debug: 'DBG', } -export function TerminalLine({ log }: TerminalLineProps) { +/** + * 一行日志。 + * + * **必须 memo。** 日志是「来一条就 push 一条」,每来一条 store 里的数组就是新的, + * 于是整个列表重渲染;而这个列表最多留 500 条 —— 不做 memo 就是每来一行重渲染 500 行, + * 每行还要跑 5 次 `cn()`(tailwind-merge 不便宜)。爬虫在跑的时候日志是成片来的, + * 主线程直接被占满,表现就是**点什么都没反应**(点折叠最容易注意到,因为那一下还要 + * 把整份列表挂载/卸载一遍)。 + * + * `log` 对象在数组里是稳定引用,所以 memo 之后只有新来的那一行会渲染。 + */ +export const TerminalLine = memo(function TerminalLine({ log }: TerminalLineProps) { const config = levelConfig[log.level] || levelConfig.info return ( @@ -67,4 +80,4 @@ export function TerminalLine({ log }: TerminalLineProps) { ) -} +})