mcpField
F
frontend-review-performance

frontend-review-performance

github.com/mizchi测试与质量41651 次安装1 周前更新
代码仓库

关于 frontend-review-performance

这项技能用于检查 React 前端的渲染性能,涵盖记忆化、大型列表、并发功能和渲染架构,并要求先进行性能分析再提出更改建议。

主要功能

  1. 01检查记忆化的使用及正确性
  2. 02找出缺少虚拟滚动的大型列表
  3. 03评估并发渲染功能的机会
  4. 04检查 Context 引发的重新渲染
  5. 05检查 Canvas 或 WebGL 的渲染分离

适用场景

  1. 01审查 React 渲染性能风险
  2. 02找出可能需要虚拟化的大型列表
  3. 03规划优化前的性能分析

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mizchi/skills --skill frontend-review-performance

安装后在 Claude Code 中输入/frontend-review-performance确认已加载。

附带文件README.md

详细介绍

前端审查 — 渲染性能

你正在审查 React 前端的渲染性能。最常见的 AI 生成问题包括:未经测量就到处使用 memo / useCallback / useMemo(或者完全不用)、大型列表缺少虚拟滚动,以及 Context 变化导致无关组件重新渲染。

流程

  1. 检查 package.json 中与性能相关的包(@tanstack/react-virtual、react-window、@welldone-software/why-did-you-render 等)。
  2. 搜索现有的 memo 用法:
    grep -rn "React\.memo\|useMemo\|useCallback" src/ --include='*.tsx' --include='*.ts' | wc -l
    grep -rn "useVirtualizer\|FixedSizeList\|VariableSizeList" src/ --include='*.tsx' | wc -l
    grep -rn "useTransition\|useDeferredValue\|startTransition" src/ --include='*.tsx' | wc -l
    
  3. 找出渲染列表规模最大的组件(查找对没有大小限制的数组调用 .map( 的情况)。
  4. 查找变化频繁、可能导致大范围重新渲染的 Context provider。
  5. 对于 iot-ops / map / chart 应用:检查繁重的渲染是在 React state 中执行,还是通过 canvas/WebGL ref 执行。

优先使用 Profiler 的原则

未经性能分析,不要建议使用 memo / useCallback / useMemo。 过早进行记忆化会增加认知负担,还可能降低性能(每个 hook 都有开销)。

撰写报告时,每条优化建议前都加上:“经性能分析确认每次交互会触发 X 次重新渲染后,可考虑 Y。”

记忆化正确性

当存在记忆化(或建议使用记忆化)时,检查以下常见错误:

React.memo
  • React.memo 是否用于接收父组件稳定属性的组件?
  • 父组件是否在每次渲染时都传入新的对象 / 数组 / 函数引用(导致 memo 失效)?
// Bad: new array on every render — memo is useless
<List items={data.filter(x => x.active)} />

// Good: stable reference with useMemo
const activeItems = useMemo(() => data.filter(x => x.active), [data]);
<List items={activeItems} />
useCallback
  • 将回调传给由 memo 包装的子组件时,是否使用了 useCallback?
  • 依赖数组是否准确(没有遗漏或不必要的依赖项)?
// Bad: new function reference every render
<Button onClick={() => handleDelete(id)} />

// Good: stable reference
const handleDeleteClick = useCallback(() => handleDelete(id), [id, handleDelete]);
<Button onClick={handleDeleteClick} />
useMemo
  • useMemo 是否用于耗时计算(对大型数组进行筛选 / 排序 / 聚合),而不是简单操作(字符串拼接、布尔值检查)?
  • 依赖数组是否正确?

虚拟滚动

对于包含 100 项以上的列表,若要获得可接受的性能,几乎总是需要使用虚拟滚动。

推荐使用:@tanstack/react-virtual(适用于任何布局,不受 CSS 限制)。

const rowVirtualizer = useVirtualizer({
  count: items.length,
  getScrollElement: () => parentRef.current,
  estimateSize: () => 48,
});

return (
  <div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
    <div style={{ height: `${rowVirtualizer.getTotalSize()}px`, position: 'relative' }}>
      {rowVirtualizer.getVirtualItems().map(vItem => (
        <div key={vItem.key} style={{ position: 'absolute', top: vItem.start, height: vItem.size }}>
          <ListItem item={items[vItem.index]} />
        </div>
      ))}
    </div>
  </div>
);

标记任何对超过 100 项的数组进行映射、但未使用虚拟滚动的列表。

并发特性(React 18+)

  • useTransition — 将繁重的非紧急状态更新包装起来,以保持 UI 响应灵敏:
const [isPending, startTransition] = useTransition();
const handleFilterChange = (q: string) => {
  startTransition(() => setFilterQuery(q));
};
  • useDeferredValue — 延迟会驱动繁重渲染的值:
const deferredQuery = useDeferredValue(filterQuery);
const filtered = useMemo(() => items.filter(i => i.name.includes(deferredQuery)), [deferredQuery, items]);

标记每次按键都会阻塞主线程的繁重筛选 / 排序操作——这些操作适合使用 useTransition。

Canvas / WebGL 分离(iot-ops / map / chart 应用)

对于数据密集型 UI(实时仪表盘、地图叠加层、图表),不应使用 React state 来处理逐帧更新。

检查以下方面:

  • 高频数据(传感器读数、地图图块更新、图表数据)是否绕过 React state,通过 useRef 直接传入 canvas/WebGL。
  • React 是否只负责控制布局外壳和控制面板,而由 canvas/WebGL 层独立处理渲染。
// Pattern: React controls mount; canvas reads data via ref
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
  const renderer = new WebGLRenderer(canvasRef.current!);
  const unsub = sensorStream.subscribe(data => renderer.update(data)); // no setState
  return unsub;
}, []);

输出

将报告写入 <client-repo>/.frontend-review/report/latest/md/performance-review.md,内容包括:

  • 性能分析建议:首先测量什么,以及如何测量(React DevTools Profiler、why-did-you-render)
  • 记忆化缺失 / 误用:每项发现的文件:行号引用
  • 虚拟滚动候选项:组件名称、估计列表大小
  • 并发特性机会:会阻塞线程的交互
  • Canvas/WebGL 评估(如适用):高频数据是否绕过 React state?
  • 建议的 PR:每个 PR 优化一项,并在 PR 描述中提供性能分析基准

控制在 200 行以内。没有性能分析证据的建议必须明确标记为“未确认 — 请先进行性能分析”。

边界

  • 不要运行性能分析会话——只描述要测量的内容和方法。
  • 不要在没有测量计划的情况下提出优化建议。
  • 不要修改客户端仓库中的源文件。
  • 状态管理架构(store 设计、selector 粒度)由 frontend-review-state 覆盖。

参考

  • 检查清单:24-rendering-performance.md、23-state-management.md、C2-lighthouse.md
  • 工具:React DevTools Profiler、@welldone-software/why-did-you-render、@tanstack/react-virtual

评论

支持 Markdown