前端 & AI 面试题库
React

React 性能优化

React 性能优化实战

主问题:你有做过性能优化吗?具体怎么做的?

核心回答

做过 React 前端和 RAG-Agent AI 应用的性能优化,核心思路是"数据驱动+分维度突破"——先通过工具定位瓶颈,再针对性优化,最后量化效果:

  1. 工具选型:Lighthouse(加载指标)、Chrome Performance(运行时性能)、React DevTools Profiler(组件渲染)、自定义埋点(生产环境监控)。

  2. 分维度优化

    • 加载性能:用 Next.js 做 SSR/SSG 提速首屏(LCP 从 2.8s 降至 1.1s);React.lazy+Suspense 代码分割(首屏 JS 包从 800KB 降至 120KB);资源压缩+CDN+缓存+懒加载(静态资源加载提速 75%)。

    • 渲染性能React.memo/useMemo/useCallback 防重复渲染;虚拟列表(react-window)解决 5000+ 条数据卡顿(FPS 稳定 60 帧);拆分长任务+Web Worker 处理大数据(长任务数量从 6 个降至 0);减少重绘回流(样式集中修改、脱离文档流)。

    • AI 应用专项:向量数据库索引优化(HNSW 替代暴力搜索,检索延迟从 800ms 降至 250ms);Redis 缓存高频检索结果(缓存命中率 60%);LLM 流式输出+模型降级(响应时间从 1.5s 降至 300ms)。

  3. 量化效果:前端项目首屏加载从 3.5s 降至 1.2s(提速 66%),AI 应用问答响应从 2.3s 降至 600ms(提速 74%),生产环境卡顿率从 15% 降至 2%。

延伸问题-回答

  1. 延伸问题:如何排查 React 项目的内存泄漏?

回答:①工具:Chrome Memory 面板(Heap Snapshot 对比,查找未回收的 DOM/组件实例);②常见场景:未清除的定时器/事件监听、闭包引用组件实例、组件卸载后仍执行 setState;③解决方法:useEffect 中清理副作用(清除定时器、事件监听);用 AbortController 取消异步请求;避免全局变量存储组件数据。

  1. 延伸问题:React 18 的新特性如何助力性能优化?

回答:①自动批处理:合并多状态更新,减少渲染次数;②useTransition/useDeferredValue:非紧急更新不阻塞紧急交互;③并发渲染:拆分渲染任务,高优先级任务优先执行;④Suspense 增强:避免异步操作导致的白屏,提升首屏感知速度。

3. React 性能优化的具体方法

1. 组件优化

// 使用 React.memo 避免不必要的重渲染
const ExpensiveComponent = React.memo(({ data }) => {
  return <div>{data}</div>;
}, (prevProps, nextProps) => {
  return prevProps.data === nextProps.data; // 自定义比较
});

// 使用 useMemo 缓存计算结果
const expensiveValue = useMemo(() => {
  return computeExpensiveValue(a, b);
}, [a, b]);

// 使用 useCallback 缓存函数
const handleClick = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

2. 列表优化

// 使用虚拟列表
import { FixedSizeList } from 'react-window';

<FixedSizeList
  height={600}
  itemCount={10000}
  itemSize={50}
  width="100%"
>
  {Row}
</FixedSizeList>

// 使用 key 优化
{items.map(item => (
  <Item key={item.id} data={item} />
))}

3. 代码分割

// 路由级别的代码分割
const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

<Suspense fallback={<Loading />}>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/about" element={<About />} />
  </Routes>
</Suspense>

4. 状态管理优化

// 使用 Context 时拆分 Context
// 避免所有组件都订阅同一个 Context
const UserContext = createContext();
const ThemeContext = createContext();

// 使用状态管理库(Redux、Zustand)时
// 只订阅需要的状态
const userName = useSelector(state => state.user.name);

5. 避免在渲染中创建对象

// 不推荐:每次渲染都创建新对象
<Component style={{ color: 'red' }} />

// 推荐:提取到组件外部或使用 useMemo
const style = { color: 'red' };
<Component style={style} />

6. 使用 useTransition 优化非紧急更新

const [isPending, startTransition] = useTransition();

const handleSearch = (value) => {
  setInputValue(value); // 紧急更新
  startTransition(() => {
    setSearchResults(filterResults(value)); // 非紧急更新
  });
};

7. 使用 useDeferredValue 延迟更新

const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);

// deferredQuery 的更新不会阻塞 UI
const results = useMemo(() => {
  return search(deferredQuery);
}, [deferredQuery]);

8. 避免不必要的 Context 更新

// 拆分 Context,避免不必要的更新
const UserContext = createContext();
const UserProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  
  // 拆分 Context
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <ThemeContext.Provider value={{ theme, setTheme }}>
        {children}
      </ThemeContext.Provider>
    </UserContext.Provider>
  );
};

9. 使用 Web Workers 处理耗时任务

// 主线程
const worker = new Worker('./worker.js');
worker.postMessage({ data: largeData });
worker.onmessage = (e) => {
  setResult(e.data);
};

// worker.js
self.onmessage = (e) => {
  const result = processLargeData(e.data.data);
  self.postMessage(result);
};

10. 优化图片加载

// 使用懒加载
<img src={imageSrc} loading="lazy" alt="image" />

// 使用 Next.js Image 组件
import Image from 'next/image';
<Image src={imageSrc} width={500} height={300} />

(注:文档部分内容可能由 AI 生成)