--- tags: [React, Performance, Optimization, Frontend] create time: 2026-04-29 22:14 --- # 性能优化 ## 概述 React 性能优化的核心原则是 **"减少不必要的渲染"**。本文档从诊断工具到具体手段,提供完整的调优方法论。 ## 性能诊断工具箱 ```mermaid graph TB A[发现性能问题] --> B["选择诊断工具"] B --> C["React DevTools Profiler"] B --> D["Chrome Performance Tab"] B --> E["Lighthouse"] B --> F["Web Vitals 监控"] C --> G["定位重渲染的组件和原因"] D --> H["分析主线程阻塞时段"] E --> I["整体 LCP/FID/CLS 评分"] F --> J["生产环境真实用户数据"] style C fill:#61DAFB,color:#000 style H fill:#F5A87D,color:#000 ``` ### React DevTools Profiler 使用要点 1. 录制期间进行关键交互(点击、输入) 2. 观察 **Commit 颜色** —— 红色越深表示重渲染越多 3. 展开组件树,关注 "why did this render" 原因 4. 对比优化前后的 Commit 时间变化 ## React.memo —— 阻止子组件重渲染 ```tsx const ExpensiveList = React.memo(({ items }: { items: Item[] }) => { // props.items 引用不变时,跳过整个子树的 re-render return ( ); }, (prevProps, nextProps) => prevProps.items === nextProps.items); // 自定义比较函数 ``` > [!warning] React.memo 的适用边界 > - 只对**纯组件**有用——相同 props 必须产生相同的输出 > - 父组件每次传新对象/函数作 prop → memo 无效 > - 简单列表(几十项以内)不需要 memo ## 虚拟列表(Virtual Scrolling) 当列表项超过数百条时,虚拟滚动通过只渲染可视区域内的 DOM 元素来大幅降低内存占用: ```tsx // 方案1:tanstack/virtual(推荐) import { useVirtualizer } from "@tanstack/react-virtual"; function VirtualList({ items }: { items: string[] }) { const parentRef = useRef(null); const virtualizer = useVirtualizer({ count: items.length, getScrollElement: () => parentRef.current, estimateSize: () => 50, // 预估每项高度 overscan: 5, // 视口上下各多渲染 5 项 }); return (
{virtualizer.getVirtualItems().map(virtualRow => (
{items[virtualRow.index]}
))}
); } ``` > [!tip] 何时需要虚拟列表? > - 列表项 > ~50 且每帧渲染耗时可感知 > - 固定高度的项目比可变高度更容易实现 > - React Window / React Virtualized 是老牌的成熟方案 ## Code Splitting ### 路由级拆分 ```tsx // Next.js App Router(内置) const AdminPage = lazy(() => import("./pages/Admin")); // vite + React Router const Settings = lazy(() => import(/* vite: preload */ "./pages/Settings")); ``` ### 组件级拆分 ```tsx import dynamic from "next/dynamic"; // 不加载图表库直到真正需要 const Chart = dynamic(() => import("recharts"), { ssr: false }); // 或带 loading fallback const HeavyEditor = dynamic(() => import("@monaco-editor/react"), { loading: () =>

Loading editor...

, ssr: false, }); ``` ### Bundle 分析与优化 ```bash # 安装插件 npm install --save-dev rollup-plugin-visualizer # 或在 Next.js 中使用 next-bundle-analyzer # 生成可视化报告 npx run build && npx visualizer ``` > [!tip] Bundle 大小目标 > | 层级 | 目标大小(gzipped)| > |------|---------------------| > | 首屏 chunk | < 150KB | > | 单个 chunk | < 300KB | > | JS Total | < 500KB(SPA)/ < 200KB(PWA) | ## Lighthouse 关键指标调优 | 指标 | 含义 | 优化方向 | |------|------|----------| | **FCP**(First Contentful Paint) | 首次内容绘制 | 减小首屏 HTML/JS 体积 | | **LCP**(Largest Contentful Paint) | 最大内容绘制 | 图片懒加载、预加载关键资源 | | **INP**(Interaction to Next Paint) | 交互响应延迟 | useTransition、删除同步 heavy work | | **CLS**(Cumulative Layout Shift) | 布局偏移 | 预留图片宽高、避免字体闪烁 | ## 关联笔记