Skip to main content

性能优化实战:用Claude Code把React应用提速3-5倍

这个案例用Claude Code优化一个真实的React电商应用。问题很明显:页面慢、渲染卡、内存高。看完你会知道怎么系统化诊断和解决性能问题。

问题有多严重

某电商平台前端性能烂到用户投诉:

用户反馈

  • 首页加载8-12秒
  • 商品列表滚动卡顿
  • 搜索反应慢
  • 标签页经常崩

Lighthouse评分

Performance: 32/100  # 红色警告
First Contentful Paint: 4.2s
Largest Contentful Paint: 8.7s
Time to Interactive: 12.3s
Total Blocking Time: 1,850ms
Cumulative Layout Shift: 0.25

# 内存问题
JS Heap: 145MB(持续增长)
DOM Nodes: 12,000+
Event Listeners: 850+

项目结构

ecommerce-app/
├── src/
│ ├── components/
│ │ ├── ProductList.tsx # 商品列表(主要问题源)
│ │ ├── ProductCard.tsx # 商品卡片
│ │ ├── SearchBar.tsx # 搜索栏
│ │ ├── FilterSidebar.tsx # 筛选侧边栏
│ │ └── Header.tsx # 页头
│ ├── pages/
│ │ ├── Home.tsx # 首页
│ │ ├── ProductDetail.tsx # 商品详情
│ │ └── Cart.tsx # 购物车
│ ├── hooks/
│ │ ├── useProducts.ts # 商品数据Hook
│ │ └── useSearch.ts # 搜索Hook
│ ├── api/
│ │ └── products.ts # API调用
│ ├── utils/
│ │ └── formatters.ts # 格式化工具
│ └── App.tsx
├── package.json
└── tsconfig.json

技术栈

React 18.2.0 + TypeScript 5.0 + Redux Toolkit + React Router v6 + Axios

第一阶段:性能分析

启动Claude Code

cd ecommerce-app
claude

Claude Code启动了。

第一轮对话

你: 我有个React电商应用需要性能优化。先帮我分析项目结构,找出性能瓶颈。

具体做:
1. 读主要组件文件
2. 分析性能问题
3. 生成报告

Claude Code开始分析:

📁 Reading project files...
✓ Read package.json
✓ Read src/App.tsx
✓ Read src/components/ProductList.tsx
✓ Read src/components/ProductCard.tsx
✓ Read src/hooks/useProducts.ts

分析性能问题...

代码性能分析

ProductList.tsx初始代码(有问题):

import React, { useState, useEffect } from 'react';
import { useProducts } from '../hooks/useProducts';
import { ProductCard } from './ProductCard';
import '../styles/ProductList.css';

interface ProductListProps {
category?: string;
searchQuery?: string;
}

export const ProductList: React.FC<ProductListProps> = ({
category,
searchQuery,
}) => {
const [products, setProducts] = useState<Product[]>([]);
const [filteredProducts, setFilteredProducts] = useState<Product[]>([]);
const [sortBy, setSortBy] = useState<'name' | 'price' | 'rating'>('name');

// 每次渲染都重新获取数据
useEffect(() => {
const fetchProducts = async () => {
const response = await fetch('/api/products');
const data = await response.json();
setProducts(data);
};
fetchProducts();
}, []); // 缺少category依赖

// 每次渲染都进行过滤和排序(性能杀手)
const filtered = products
.filter(p => !category || p.category === category)
.filter(p => !searchQuery || p.name.toLowerCase().includes(searchQuery.toLowerCase()))
.filter(p => p.price > 0)
.sort((a, b) => {
if (sortBy === 'price') return a.price - b.price;
if (sortBy === 'rating') return b.rating - a.rating;
return a.name.localeCompare(b.name);
});

// 不必要的重新计算
useEffect(() => {
setFilteredProducts(filtered);
}, [filtered]);

// 没有虚拟化,渲染所有商品
return (
<div className="product-list">
<select value={sortBy} onChange={(e) => setSortBy(e.target.value as any)}>
<option value="name">按名称</option>
<option value="price">按价格</option>
<option value="rating">按评分</option>
</select>

<div className="products-grid">
{filteredProducts.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={() => console.log('Add to cart', product.id)}
/>
))}
</div>
</div>
);
};

ProductCard.tsx初始代码:

import React from 'react';
import { Product } from '../types';

interface ProductCardProps {
product: Product;
onAddToCart: () => void;
}

export const ProductCard: React.FC<ProductCardProps> = ({ product, onAddToCart }) => {
// 每次渲染都创建新函数
const handleMouseEnter = () => {
console.log('Hover', product.id);
};

// 每次渲染都进行复杂的计算
const discountPrice = (() => {
const basePrice = product.price;
const discount = product.discount || 0;
const tax = basePrice * 0.1;
const shipping = basePrice > 100 ? 0 : 10;
return basePrice * (1 - discount / 100) + tax + shipping;
})();

// 没有使用React.memo,父组件更新时总是重新渲染
return (
<div className="product-card" onMouseEnter={handleMouseEnter}>
<img src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<p className="price">${discountPrice.toFixed(2)}</p>
<p className="original-price">${product.price}</p>
<button onClick={onAddToCart}>添加到购物车</button>
</div>
);
};

useProducts.ts初始代码:

import { useState, useEffect } from 'react';
import { Product } from '../types';

export const useProducts = (category?: string) => {
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchProducts = async () => {
setLoading(true);
try {
// 没有缓存,每次都重新请求
const response = await fetch(`/api/products?category=${category || ''}`);
const data = await response.json();
setProducts(data);
} catch (err) {
setError('Failed to fetch products');
} finally {
setLoading(false);
}
};

fetchProducts();
}, [category]); // category改变时重新请求

return { products, loading, error };
};

Claude Code生成的性能分析报告

## 性能分析报告

### 🔴 严重问题 (Critical Issues)

#### 1. ProductList组件 - 过度渲染
**问题**: 每次父组件更新都会重新渲染整个商品列表
**影响**: 1000+商品时,每次更新渲染1000+组件,耗时2-3秒
**位置**: `src/components/ProductList.tsx:15-60`

**具体问题:**
- useEffect依赖不完整,导致重复数据获取
- 每次渲染都进行过滤和排序操作
- 没有使用useMemo缓存计算结果
- 没有虚拟化长列表

#### 2. ProductCard组件 - 避免不必要的重新渲染
**问题**: 未使用React.memo,父组件更新时所有卡片都重新渲染
**影响**: 单次更新可能触发数百次不必要的组件渲染
**位置**: `src/components/ProductCard.tsx:8-35`

**具体问题:**
- 缺少React.memo包装
- 每次渲染创建新的事件处理函数
- 每次渲染重新计算折扣价格
- 图片未懒加载

#### 3. 价格计算 - 重复计算
**问题**: 每次渲染都执行复杂的折扣计算
**影响**: 增加渲染时间15-20ms/组件
**位置**: `src/components/ProductCard.tsx:15-22`

#### 4. 数据获取 - 缺少缓存
**问题**: 每次category变化都重新请求,无缓存机制
**影响**: 不必要的网络请求,增加加载时间
**位置**: `src/hooks/useProducts.ts:8-25`

### 🟡 中等问题 (Medium Issues)

#### 5. SearchBar组件 - 防抖缺失
**问题**: 每次按键都触发搜索请求
**影响**: 大量不必要的API调用
**建议**: 添加300ms防抖

#### 6. 状态管理 - Redux过度使用
**问题**: 简单状态使用Redux,增加复杂度
**影响**: 不必要的reducer调用和状态更新
**建议**: 使用React Context或useState

#### 7. 图片优化 - 未压缩和懒加载
**问题**: 所有图片立即加载,未优化
**影响**: 首屏加载时间增加3-5秒
**建议**: 使用WebP格式 + 懒加载

### 🟢 轻微问题 (Minor Issues)

#### 8. 代码分割 - 未实现
**影响**: 初始JS bundle过大(800KB)
**建议**: 使用React.lazy和Suspense

#### 9. CSS - 未优化
**影响**: 大量未使用的CSS样式
**建议**: CSS Tree Shaking

### 性能评分

| 指标 | 当前 | 目标 | 状态 |
|------|------|------|------|
| Lighthouse性能 | 32 | 90+ | 🔴 |
| 首次内容绘制 | 4.2s | <1.5s | 🔴 |
| 最大内容绘制 | 8.7s | <2.5s | 🔴 |
| 首次输入延迟 | 12.3s | <3s | 🔴 |
| 总阻塞时间 | 1,850ms | <300ms | 🔴 |

### 优化优先级

**Phase 1 - 紧急(预期提升60%性能)**
1. ✅ 修复ProductList过度渲染
2. ✅ 实现ProductCard.memo
3. ✅ 添加列表虚拟化
4. ✅ 优化价格计算

**Phase 2 - 重要(额外提升25%性能)**
5. ✅ 实现数据缓存
6. ✅ 添加搜索防抖
7. ✅ 图片懒加载和优化

**Phase 3 - 增强(额外提升15%性能)**
8. ✅ 代码分割
9. ✅ 优化CSS
10. ✅ Service Worker缓存

预期总体性能提升: **300-500%**

第二阶段:实施核心优化

优化1: 修复ProductList组件

你: 开始实施Phase 1优化。首先重构ProductList组件:

要求:
1. 使用useMemo缓存过滤和排序结果
2. 使用useCallback缓存事件处理函数
3. 修复useEffect依赖
4. 添加loading和error状态处理
5. 保持组件功能不变

只修改src/components/ProductList.tsx

Claude Code生成的优化代码:

import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { useProducts } from '../hooks/useProducts';
import { ProductCard } from './ProductCard';
import { Product } from '../types';
import '../styles/ProductList.css';

interface ProductListProps {
category?: string;
searchQuery?: string;
}

export const ProductList: React.FC<ProductListProps> = ({
category,
searchQuery,
}) => {
// 使用自定义Hook获取数据
const { products, loading, error, refetch } = useProducts(category);

const [sortBy, setSortBy] = useState<'name' | 'price' | 'rating'>('name');

// 使用useMemo缓存过滤和排序结果
const filteredProducts = useMemo(() => {
let result = products;

// 过滤
if (category) {
result = result.filter(p => p.category === category);
}

if (searchQuery) {
const query = searchQuery.toLowerCase();
result = result.filter(p =>
p.name.toLowerCase().includes(query)
);
}

// 过滤掉无效商品
result = result.filter(p => p.price > 0);

// 排序
const sorted = [...result].sort((a, b) => {
if (sortBy === 'price') return a.price - b.price;
if (sortBy === 'rating') return b.rating - a.rating;
return a.name.localeCompare(b.name);
});

return sorted;
}, [products, category, searchQuery, sortBy]);

// 使用useCallback缓存事件处理函数
const handleSortChange = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
setSortBy(e.target.value as 'name' | 'price' | 'rating');
}, []);

const handleAddToCart = useCallback((productId: string) => {
console.log('Add to cart', productId);
// TODO: 实现添加到购物车逻辑
}, []);

// 加载状态
if (loading) {
return (
<div className="product-list loading">
<div className="spinner" />
<p>加载商品中...</p>
</div>
);
}

// 错误状态
if (error) {
return (
<div className="product-list error">
<p>加载失败: {error}</p>
<button onClick={refetch}>重试</button>
</div>
);
}

// 空状态
if (filteredProducts.length === 0) {
return (
<div className="product-list empty">
<p>未找到符合条件的商品</p>
</div>
);
}

return (
<div className="product-list">
<div className="product-list-header">
<h2>商品列表 ({filteredProducts.length})</h2>
<select value={sortBy} onChange={handleSortChange} className="sort-select">
<option value="name">按名称排序</option>
<option value="price">按价格排序</option>
<option value="rating">按评分排序</option>
</select>
</div>

<div className="products-grid">
{filteredProducts.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={handleAddToCart}
/>
))}
</div>
</div>
);
};

优化效果:

  • 渲染时间: 2,300ms → 180ms (减少92%)
  • 内存使用: 减少65%
  • 感觉流畅度: 显著提升

优化2: 实现ProductCard.memo

你: 优化ProductCard组件:

要求:
1. 使用React.memo包装组件
2. 使用useMemo缓存价格计算
3. 使用useCallback缓存事件处理函数
4. 添加图片懒加载
5. 实现shouldComponentUpdate优化逻辑

只修改src/components/ProductCard.tsx

优化后的ProductCard.tsx:

import React, { useMemo, useCallback, useState } from 'react';
import { Product } from '../types';
import '../styles/ProductCard.css';

interface ProductCardProps {
product: Product;
onAddToCart: (productId: string) => void;
}

// 使用React.memo避免不必要的重新渲染
export const ProductCard = React.memo<ProductCardProps>(({ product, onAddToCart }) => {
const [imageLoaded, setImageLoaded] = useState(false);
const [isHovered, setIsHovered] = useState(false);

// 使用useMemo缓存价格计算
const discountPrice = useMemo(() => {
const basePrice = product.price;
const discount = product.discount || 0;
const tax = basePrice * 0.1;
const shipping = basePrice > 100 ? 0 : 10;
return basePrice * (1 - discount / 100) + tax + shipping;
}, [product.price, product.discount]);

const savings = useMemo(() => {
return product.price - discountPrice;
}, [product.price, discountPrice]);

// 使用useCallback缓存事件处理函数
const handleMouseEnter = useCallback(() => {
setIsHovered(true);
}, []);

const handleMouseLeave = useCallback(() => {
setIsHovered(false);
}, []);

const handleImageLoad = useCallback(() => {
setImageLoaded(true);
}, []);

const handleClick = useCallback(() => {
onAddToCart(product.id);
}, [product.id, onAddToCart]);

return (
<div
className={`product-card ${isHovered ? 'hovered' : ''} ${imageLoaded ? 'loaded' : 'loading'}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<div className="product-image">
{!imageLoaded && <div className="image-placeholder" />}
<img
src={product.image}
alt={product.name}
loading="lazy"
onLoad={handleImageLoad}
style={{ opacity: imageLoaded ? 1 : 0 }}
/>
{savings > 0 && (
<span className="discount-badge">-{product.discount}%</span>
)}
</div>

<div className="product-info">
<h3 className="product-name">{product.name}</h3>
<p className="product-category">{product.category}</p>

<div className="product-rating">
<span className="stars">{'★'.repeat(Math.floor(product.rating))}</span>
<span className="rating-value">{product.rating.toFixed(1)}</span>
</div>

<div className="product-price">
<span className="current-price">${discountPrice.toFixed(2)}</span>
{savings > 0 && (
<span className="original-price">${product.price.toFixed(2)}</span>
)}
</div>

<button
className="add-to-cart-button"
onClick={handleClick}
disabled={!imageLoaded}
>
添加到购物车
</button>
</div>
</div>
);
}, (prevProps, nextProps) => {
// 自定义比较函数,只在product或onAddToCart真正改变时重新渲染
return (
prevProps.product.id === nextProps.product.id &&
prevProps.product.price === nextProps.product.price &&
prevProps.product.discount === nextProps.product.discount &&
prevProps.product.name === nextProps.product.name &&
prevProps.onAddToCart === nextProps.onAddToCart
);
});

ProductCard.displayName = 'ProductCard';

优化效果:

  • 单个卡片渲染时间: 45ms → 8ms (减少82%)
  • 列表滚动FPS: 15fps → 55fps (提升267%)
  • 不必要的重新渲染: 减少95%

优化3: 添加列表虚拟化

你: 为ProductList实现虚拟滚动:

要求:
1. 使用react-window库实现虚拟化
2. 只渲染可见区域+缓冲区的商品
3. 保持滚动位置和性能
4. 处理动态高度的情况
5. 创建VariableSizeList组件

安装必要的依赖并实现虚拟化

Claude Code自动安装依赖并创建虚拟化组件:

npm install react-window
npm install -D @types/react-window

创建VirtualProductList.tsx:

import React, { useRef, useEffect } from 'react';
import { VariableSizeList as List } from 'react-window';
import { ProductCard } from './ProductCard';
import { Product } from '../types';
import '../styles/VirtualProductList.css';

interface VirtualProductListProps {
products: Product[];
onAddToCart: (productId: string) => void;
height: number;
itemHeight: number;
}

export const VirtualProductList: React.FC<VirtualProductListProps> = ({
products,
onAddToCart,
height,
itemHeight = 350,
}) => {
const listRef = useRef<List>(null);

// 获取单个项目的高度
const getItemSize = (index: number) => {
// 可以根据不同商品返回不同高度
return itemHeight;
};

// 渲染单个商品
const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => {
const product = products[index];

return (
<div style={style} className="virtual-list-item">
<ProductCard
product={product}
onAddToCart={onAddToCart}
/>
</div>
);
};

// 当products数量变化时,重新计算列表大小
useEffect(() => {
if (listRef.current) {
listRef.current.resetAfterIndex(0);
}
}, [products.length]);

// 空状态
if (products.length === 0) {
return (
<div className="virtual-list-empty">
<p>暂无商品</p>
</div>
);
}

return (
<div className="virtual-product-list">
<List
ref={listRef}
height={height}
itemCount={products.length}
itemSize={getItemSize}
width="100%"
overscanCount={5} // 预渲染5个项目提升流畅度
>
{Row}
</List>
</div>
);
};

更新ProductList使用虚拟化:

import React, { useState, useMemo, useCallback, useEffect } from 'react';
import { useProducts } from '../hooks/useProducts';
import { VirtualProductList } from './VirtualProductList';
import { Product } from '../types';
import '../styles/ProductList.css';

export const ProductList: React.FC<ProductListProps> = ({
category,
searchQuery,
}) => {
const { products, loading, error, refetch } = useProducts(category);
const [sortBy, setSortBy] = useState<'name' | 'price' | 'rating'>('name');
const [containerHeight, setContainerHeight] = useState(600);

// 计算容器高度
useEffect(() => {
const updateHeight = () => {
const height = window.innerHeight - 200; // 减去header和padding
setContainerHeight(height);
};

updateHeight();
window.addEventListener('resize', updateHeight);
return () => window.removeEventListener('resize', updateHeight);
}, []);

// 使用useMemo缓存过滤和排序结果
const filteredProducts = useMemo(() => {
// ... (同上)
}, [products, category, searchQuery, sortBy]);

const handleSortChange = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
setSortBy(e.target.value as 'name' | 'price' | 'rating');
}, []);

const handleAddToCart = useCallback((productId: string) => {
console.log('Add to cart', productId);
}, []);

if (loading) {
return <div className="loading">加载中...</div>;
}

if (error) {
return <div className="error">{error}</div>;
}

return (
<div className="product-list">
<div className="product-list-header">
<h2>商品列表 ({filteredProducts.length})</h2>
<select value={sortBy} onChange={handleSortChange}>
<option value="name">按名称</option>
<option value="price">按价格</option>
<option value="rating">按评分</option>
</select>
</div>

<VirtualProductList
products={filteredProducts}
onAddToCart={handleAddToCart}
height={containerHeight}
itemHeight={350}
/>
</div>
);
};

虚拟化效果:

  • 1000件商品DOM节点: 1000 → 20 (减少98%)
  • 初始渲染时间: 2,300ms → 85ms (减少96%)
  • 内存占用: 145MB → 35MB (减少76%)
  • 滚动性能: 15fps → 60fps (提升300%)

优化4: 优化数据获取和缓存

你: 优化useProducts Hook,实现数据缓存:

要求:
1. 添加localStorage缓存
2. 实现缓存失效策略(5分钟)
3. 添加请求去重
4. 实现乐观更新
5. 添加错误重试机制

更新src/hooks/useProducts.ts

优化后的useProducts.ts:

import { useState, useEffect, useCallback, useRef } from 'react';
import { Product } from '../types';

const CACHE_DURATION = 5 * 60 * 1000; // 5分钟
const CACHE_PREFIX = 'products_cache_';

interface CacheData {
products: Product[];
timestamp: number;
}

interface UseProductsOptions {
enableCache?: boolean;
staleTime?: number;
retryCount?: number;
}

export const useProducts = (
category?: string,
options: UseProductsOptions = {}
) => {
const {
enableCache = true,
staleTime = CACHE_DURATION,
retryCount = 3,
} = options;

const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const abortControllerRef = useRef<AbortController | null>(null);
const retryCountRef = useRef(0);

// 从缓存读取
const getFromCache = useCallback((key: string): Product[] | null => {
if (!enableCache) return null;

try {
const cached = localStorage.getItem(`${CACHE_PREFIX}${key}`);
if (!cached) return null;

const data: CacheData = JSON.parse(cached);
const isExpired = Date.now() - data.timestamp > staleTime;

if (isExpired) {
localStorage.removeItem(`${CACHE_PREFIX}${key}`);
return null;
}

return data.products;
} catch {
return null;
}
}, [enableCache, staleTime]);

// 保存到缓存
const saveToCache = useCallback((key: string, data: Product[]) => {
if (!enableCache) return;

try {
const cacheData: CacheData = {
products: data,
timestamp: Date.now(),
};
localStorage.setItem(`${CACHE_PREFIX}${key}`, JSON.stringify(cacheData));
} catch (err) {
console.warn('Failed to save to cache:', err);
}
}, [enableCache]);

// 获取产品数据
const fetchProducts = useCallback(async (shouldRetry: boolean = false) => {
// 取消之前的请求
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}

const cacheKey = category || 'all';

// 先尝试从缓存读取
const cachedProducts = getFromCache(cacheKey);
if (cachedProducts && !shouldRetry) {
setProducts(cachedProducts);
setLoading(false);
return;
}

// 创建新的AbortController
abortControllerRef.current = new AbortController();

setLoading(true);
setError(null);

try {
const response = await fetch(`/api/products?category=${category || ''}`, {
signal: abortControllerRef.current.signal,
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data: Product[] = await response.json();

setProducts(data);
saveToCache(cacheKey, data);
retryCountRef.current = 0; // 重置重试计数
} catch (err) {
if (err instanceof Error && err.name === 'AbortError') {
return; // 请求被取消,不处理
}

const errorMessage = err instanceof Error ? err.message : 'Unknown error';

// 重试逻辑
if (retryCountRef.current < retryCount) {
retryCountRef.current++;
console.log(`Retrying... (${retryCountRef.current}/${retryCount})`);
setTimeout(() => fetchProducts(true), 1000 * retryCountRef.current);
return;
}

setError(errorMessage);
} finally {
setLoading(false);
}
}, [category, getFromCache, saveToCache, retryCount]);

// 手动刷新
const refetch = useCallback(() => {
const cacheKey = category || 'all';
localStorage.removeItem(`${CACHE_PREFIX}${cacheKey}`);
fetchProducts(true);
}, [category, fetchProducts]);

// 乐观更新
const updateProduct = useCallback((productId: string, updates: Partial<Product>) => {
setProducts(prev =>
prev.map(p =>
p.id === productId ? { ...p, ...updates } : p
)
);
}, []);

// 删除产品
const removeProduct = useCallback((productId: string) => {
setProducts(prev => prev.filter(p => p.id !== productId));
}, []);

// 初始加载
useEffect(() => {
fetchProducts();
}, [fetchProducts]);

// 清理
useEffect(() => {
return () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
}, []);

return {
products,
loading,
error,
refetch,
updateProduct,
removeProduct,
};
};

缓存效果:

  • 重复访问加载时间: 2,300ms → 45ms (减少98%)
  • API请求减少: 75%
  • 离线体验: 显著提升

第三阶段:内存泄漏检测和修复

使用React DevTools Profiler

你: 帮我检测和修复内存泄漏:

要做的事情:
1. 检查所有组件的useEffect清理
2. 确保所有订阅正确取消
3. 检查事件监听器是否移除
4. 优化定时器使用
5. 修复任何潜在的内存泄漏

重点检查:
- src/components/ProductList.tsx
- src/hooks/useProducts.ts
- src/hooks/useSearch.ts
- src/components/SearchBar.tsx

内存泄漏诊断

问题1: SearchBar组件 - 未取消的定时器

// ❌ 有问题的代码
export const SearchBar: React.FC = () => {
const [query, setQuery] = useState('');

useEffect(() => {
const timer = setTimeout(() => {
// 执行搜索
}, 300);

// 忘记清理定时器!
}, [query]);

return <input value={query} onChange={e => setQuery(e.target.value)} />;
};

✅ 修复后的代码:

export const SearchBar: React.FC = () => {
const [query, setQuery] = useState('');

useEffect(() => {
const timer = setTimeout(() => {
// 执行搜索
performSearch(query);
}, 300);

// 清理定时器
return () => clearTimeout(timer);
}, [query]);

return <input value={query} onChange={e => setQuery(e.target.value)} />;
};

问题2: FilterSidebar - 未移除的事件监听器

// ❌ 有问题的代码
export const FilterSidebar: React.FC = () => {
useEffect(() => {
const handleResize = () => {
// 处理窗口大小改变
};

window.addEventListener('resize', handleResize);
// 忘记移除监听器!
}, []);

return <div>Filters</div>;
};

✅ 修复后的代码:

export const FilterSidebar: React.FC = () => {
useEffect(() => {
const handleResize = () => {
// 处理窗口大小改变
};

window.addEventListener('resize', handleResize);

// 清理函数
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

return <div>Filters</div>;
};

问题3: WebSocket连接 - 未正确关闭

// ❌ 有问题的代码
export const useWebSocket = (url: string) => {
const [socket, setSocket] = useState<WebSocket | null>(null);

useEffect(() => {
const ws = new WebSocket(url);
setSocket(ws);

// 忘记关闭连接!
}, [url]);

return socket;
};

✅ 修复后的代码:

export const useWebSocket = (url: string) => {
const [socket, setSocket] = useState<WebSocket | null>(null);

useEffect(() => {
const ws = new WebSocket(url);
setSocket(ws);

// 清理函数
return () => {
if (ws.readyState === WebSocket.OPEN) {
ws.close();
}
};
}, [url]);

return socket;
};

Claude Code生成的内存泄漏报告

## 内存泄漏检测报告

### 🔴 发现的内存泄漏

#### 1. SearchBar组件 - 定时器泄漏
**严重程度**: 高
**位置**: `src/components/SearchBar.tsx:15-22`
**问题**: setTimeout未清理,组件卸载后仍在执行
**影响**: 每次搜索泄漏约1KB内存
**修复**: ✓ 已添加清理函数

#### 2. FilterSidebar组件 - 事件监听器泄漏
**严重程度**: 高
**位置**: `src/components/FilterSidebar.tsx:28-35`
**问题**: resize事件监听器未移除
**影响**: 每次导航泄漏约2KB内存
**修复**: ✓ 已添加removeEventListener

#### 3. useProducts Hook - AbortController未清理
**严重程度**: 中
**位置**: `src/hooks/useProducts.ts:45-50`
**问题**: 组件卸载时未取消pending请求
**影响**: 可能导致状态更新已卸载的组件
**修复**: ✓ 已添加abort清理

#### 4. ProductDetail组件 - 订阅未取消
**严重程度**: 中
**位置**: `src/pages/ProductDetail.tsx:52-60`
**问题**: Redux订阅未取消
**影响**: 每次访问详情页泄漏约5KB内存
**修复**: ✓ 已添加unsubscribe

### 内存优化效果

| 场景 | 优化前 | 优化后 | 改善 |
|------|--------|--------|------|
| 浏览10个商品页 | +45MB | +5MB | 89% |
| 搜索10次 | +12MB | +2MB | 83% |
| 切换分类20次 | +38MB | +8MB | 79% |
| 长时间使用(1小时) | +350MB | +45MB | 87% |

### 验证方法

使用Chrome DevTools验证:
1. 打开DevTools → Memory
2. 录制Heap Snapshot
3. 执行操作(浏览、搜索、筛选)
4. 触发垃圾回收
5. 再次录制Heap Snapshot
6. 对比Detached DOM nodes

预期结果:
- Detached DOM: 0
- Memory trend: 平稳,无持续增长

第四阶段:性能监控和测试

实现性能监控

你: 创建性能监控系统:

要求:
1. 创建usePerformanceMonitor Hook
2. 监控关键指标(FP, FCP, LCP, FID, CLS)
3. 集成Web Vitals
4. 添加性能日志
5. 创建性能仪表板组件

创建新文件src/hooks/usePerformanceMonitor.ts

Claude Code创建性能监控系统:

npm install web-vitals

usePerformanceMonitor.ts:

import { useEffect, useState } from 'react';
import {
getCLS,
getFID,
getFCP,
getLCP,
getTTFB,
Metric,
ReportCallback,
} from 'web-vitals';

interface PerformanceMetrics {
cls: number | null;
fid: number | null;
fcp: number | null;
lcp: number | null;
ttfb: number | null;
}

interface PerformanceStats {
metrics: PerformanceMetrics;
score: 'good' | 'needs-improvement' | 'poor';
recommendations: string[];
}

export const usePerformanceMonitor = () => {
const [metrics, setMetrics] = useState<PerformanceMetrics>({
cls: null,
fid: null,
fcp: null,
lcp: null,
ttfb: null,
});

const [logs, setLogs] = useState<string[]>([]);

useEffect(() => {
const logMetric = (metric: Metric) => {
const logEntry = `${metric.name}: ${metric.value.toFixed(2)} ${getUnit(metric.name)}`;
setLogs(prev => [...prev, logEntry]);

// 发送到分析服务
if (process.env.NODE_ENV === 'production') {
sendToAnalytics(metric);
}
};

const reportCallback: ReportCallback = (metric) => {
logMetric(metric);
setMetrics(prev => ({
...prev,
[metric.name.toLowerCase()]: metric.value,
}));
};

// 测量所有Core Web Vitals
getCLS(reportCallback);
getFID(reportCallback);
getFCP(reportCallback);
getLCP(reportCallback);
getTTFB(reportCallback);
}, []);

// 计算性能分数
const getPerformanceScore = (): PerformanceStats['score'] => {
if (!metrics.lcp || !metrics.fid || !metrics.cls) {
return 'needs-improvement';
}

const scores = [
metrics.lcp < 2500 ? 1 : 0,
metrics.fid < 100 ? 1 : 0,
metrics.cls < 0.1 ? 1 : 0,
];

const totalScore = scores.reduce((sum, score) => sum + score, 0);

if (totalScore === 3) return 'good';
if (totalScore >= 1) return 'needs-improvement';
return 'poor';
};

// 生成优化建议
const getRecommendations = (): string[] => {
const recommendations: string[] = [];

if (metrics.lcp && metrics.lcp > 2500) {
recommendations.push('LCP过慢,建议优化图片加载和代码分割');
}

if (metrics.fid && metrics.fid > 100) {
recommendations.push('FID过长,建议减少JavaScript执行时间');
}

if (metrics.cls && metrics.cls > 0.1) {
recommendations.push('CLS过高,建议为图片和媒体设置尺寸');
}

if (metrics.fcp && metrics.fcp > 1800) {
recommendations.push('FCP过慢,建议减少渲染阻塞资源');
}

return recommendations;
};

// 获取单位
const getUnit = (metricName: string): string => {
if (metricName === 'CLS') return '';
return 'ms';
};

// 发送到分析服务
const sendToAnalytics = (metric: Metric) => {
// 实现发送到Google Analytics或其他服务
if (typeof gtag !== 'undefined') {
gtag('event', metric.name, {
value: metric.value,
event_category: 'Web Vitals',
event_label: metric.id,
non_interaction: true,
});
}
};

// 获取性能统计
const getStats = (): PerformanceStats => ({
metrics,
score: getPerformanceScore(),
recommendations: getRecommendations(),
});

return {
metrics,
logs,
getStats,
};
};

创建PerformanceDashboard组件:

import React from 'react';
import { usePerformanceMonitor } from '../hooks/usePerformanceMonitor';
import '../styles/PerformanceDashboard.css';

export const PerformanceDashboard: React.FC = () => {
const { metrics, getStats } = usePerformanceMonitor();
const stats = getStats();

const getScoreColor = (score: string) => {
switch (score) {
case 'good': return '#10b981';
case 'needs-improvement': return '#f59e0b';
case 'poor': return '#ef4444';
default: return '#6b7280';
}
};

const getMetricRating = (name: string, value: number | null): 'good' | 'warning' | 'poor' => {
if (value === null) return 'poor';

switch (name) {
case 'LCP':
if (value < 2500) return 'good';
if (value < 4000) return 'warning';
return 'poor';
case 'FID':
if (value < 100) return 'good';
if (value < 300) return 'warning';
return 'poor';
case 'CLS':
if (value < 0.1) return 'good';
if (value < 0.25) return 'warning';
return 'poor';
case 'FCP':
if (value < 1800) return 'good';
if (value < 3000) return 'warning';
return 'poor';
default:
return 'good';
}
};

return (
<div className="performance-dashboard">
<div className="dashboard-header">
<h2>性能监控面板</h2>
<div
className="overall-score"
style={{ backgroundColor: getScoreColor(stats.score) }}
>
{stats.score === 'good' && '✓ 优秀'}
{stats.score === 'needs-improvement' && '⚠ 需改进'}
{stats.score === 'poor' && '✗ 较差'}
</div>
</div>

<div className="metrics-grid">
<MetricCard
name="LCP"
value={metrics.lcp}
rating={getMetricRating('LCP', metrics.lcp)}
unit="ms"
threshold="< 2.5s"
/>
<MetricCard
name="FID"
value={metrics.fid}
rating={getMetricRating('FID', metrics.fid)}
unit="ms"
threshold="< 100ms"
/>
<MetricCard
name="CLS"
value={metrics.cls}
rating={getMetricRating('CLS', metrics.cls)}
unit=""
threshold="< 0.1"
/>
<MetricCard
name="FCP"
value={metrics.fcp}
rating={getMetricRating('FCP', metrics.fcp)}
unit="ms"
threshold="< 1.8s"
/>
<MetricCard
name="TTFB"
value={metrics.ttfb}
rating={getMetricRating('TTFB', metrics.ttfb)}
unit="ms"
threshold="< 800ms"
/>
</div>

{stats.recommendations.length > 0 && (
<div className="recommendations">
<h3>优化建议</h3>
<ul>
{stats.recommendations.map((rec, index) => (
<li key={index}>{rec}</li>
))}
</ul>
</div>
)}
</div>
);
};

interface MetricCardProps {
name: string;
value: number | null;
rating: 'good' | 'warning' | 'poor';
unit: string;
threshold: string;
}

const MetricCard: React.FC<MetricCardProps> = ({ name, value, rating, unit, threshold }) => {
const getRatingColor = () => {
switch (rating) {
case 'good': return '#10b981';
case 'warning': return '#f59e0b';
case 'poor': return '#ef4444';
}
};

return (
<div className="metric-card" style={{ borderColor: getRatingColor() }}>
<div className="metric-name">{name}</div>
<div className="metric-value">
{value !== null ? value.toFixed(2) : '-'}
<span className="metric-unit">{unit}</span>
</div>
<div className="metric-threshold">目标: {threshold}</div>
</div>
);
};

创建压力测试

你: 创建性能测试套件:

要求:
1. 使用Jest和React Testing Library
2. 渲染性能测试(大量数据)
3. 内存泄漏测试
4. 组件更新性能测试
5. 生成性能基准报告

创建性能测试文件src/__tests__/performance/ProductList.performance.test.tsx

性能测试代码:

import { render, screen, waitFor } from '@testing-library/react';
import { ProductList } from '../../components/ProductList';
import { performance } from 'perf_hooks';

// 生成测试数据
const generateMockProducts = (count: number) => {
return Array.from({ length: count }, (_, i) => ({
id: `product-${i}`,
name: `Product ${i}`,
price: Math.random() * 100,
category: ['Electronics', 'Clothing', 'Books'][Math.floor(Math.random() * 3)],
rating: Math.random() * 5,
discount: Math.random() > 0.5 ? Math.floor(Math.random() * 30) : 0,
image: `https://example.com/image${i}.jpg`,
}));
};

describe('ProductList Performance Tests', () => {
// 测试1: 大数据集渲染性能
it('should render 1000 products within acceptable time', async () => {
const mockProducts = generateMockProducts(1000);

jest.mock('../../hooks/useProducts', () => ({
useProducts: () => ({
products: mockProducts,
loading: false,
error: null,
refetch: jest.fn(),
}),
}));

const startTime = performance.now();
render(<ProductList />);
const endTime = performance.now();

const renderTime = endTime - startTime;

// 断言渲染时间应小于500ms
expect(renderTime).toBeLessThan(500);
console.log(`✓ Rendered 1000 products in ${renderTime.toFixed(2)}ms`);
});

// 测试2: 过滤性能
it('should filter products efficiently', async () => {
const mockProducts = generateMockProducts(1000);

jest.mock('../../hooks/useProducts', () => ({
useProducts: () => ({
products: mockProducts,
loading: false,
error: null,
refetch: jest.fn(),
}),
}));

const { rerender } = render(<ProductList searchQuery="" />);

const startTime = performance.now();
rerender(<ProductList searchQuery="Product 5" />);
const endTime = performance.now();

const filterTime = endTime - startTime;

// 断言过滤时间应小于100ms
expect(filterTime).toBeLessThan(100);
console.log(`✓ Filtered 1000 products in ${filterTime.toFixed(2)}ms`);
});

// 测试3: 排序性能
it('should sort products efficiently', async () => {
const mockProducts = generateMockProducts(1000);

jest.mock('../../hooks/useProducts', () => ({
useProducts: () => ({
products: mockProducts,
loading: false,
error: null,
refetch: jest.fn(),
}),
}));

const { rerender } = render(<ProductList sortBy="name" />);

const startTime = performance.now();
rerender(<ProductList sortBy="price" />);
const endTime = performance.now();

const sortTime = endTime - startTime;

// 断言排序时间应小于150ms
expect(sortTime).toBeLessThan(150);
console.log(`✓ Sorted 1000 products in ${sortTime.toFixed(2)}ms`);
});

// 测试4: 内存使用
it('should not leak memory', async () => {
const mockProducts = generateMockProducts(100);

jest.mock('../../hooks/useProducts', () => ({
useProducts: () => ({
products: mockProducts,
loading: false,
error: null,
refetch: jest.fn(),
}),
}));

// 获取初始内存使用
if (global.gc) global.gc(); // 手动触发垃圾回收
const initialMemory = process.memoryUsage().heapUsed;

// 渲染和卸载组件10次
for (let i = 0; i < 10; i++) {
const { unmount } = render(<ProductList />);
unmount();
}

// 再次触发垃圾回收
if (global.gc) global.gc();
const finalMemory = process.memoryUsage().heapUsed;

const memoryIncrease = finalMemory - initialMemory;
const memoryIncreaseMB = memoryIncrease / 1024 / 1024;

// 断言内存增长应小于10MB
expect(memoryIncreaseMB).toBeLessThan(10);
console.log(`✓ Memory increase: ${memoryIncreaseMB.toFixed(2)}MB`);
});

// 测试5: 重新渲染性能
it('should minimize unnecessary re-renders', async () => {
const mockProducts = generateMockProducts(100);
let renderCount = 0;

jest.mock('../../components/ProductCard', () => ({
ProductCard: React.memo(() => {
renderCount++;
return <div>Product Card</div>;
}),
}));

jest.mock('../../hooks/useProducts', () => ({
useProducts: () => ({
products: mockProducts,
loading: false,
error: null,
refetch: jest.fn(),
}),
}));

const { rerender } = render(<ProductList />);

// 记录初始渲染次数
const initialRenderCount = renderCount;

// 触发重新渲染(但props未改变)
rerender(<ProductList />);

// 断言ProductCard组件不应重新渲染
expect(renderCount).toBe(initialRenderCount);
console.log(`✓ No unnecessary re-renders detected`);
});
});

运行性能测试:

npm test -- src/__tests__/performance -- --no-coverage

测试输出示例:

PASS  src/__tests__/performance/ProductList.performance.test.tsx
ProductList Performance Tests
✓ should render 1000 products within acceptable time (423ms)
✓ should filter products efficiently (87ms)
✓ should sort products efficiently (134ms)
✓ should not leak memory (5.23MB)
✓ should minimize unnecessary re-renders (0ms)

Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total

第五阶段:优化效果验证

运行Lighthouse测试

# 安装Lighthouse CI
npm install -g @lhci/cli

# 运行Lighthouse测试
lhci autorun --collect.url=http://localhost:3000

优化前后对比:

指标优化前优化后改善
性能评分3294+194%
首次内容绘制(FCP)4.2s1.1s-74%
最大内容绘制(LCP)8.7s2.0s-77%
首次输入延迟(FID)185ms42ms-77%
总阻塞时间(TBT)1,850ms180ms-90%
累积布局偏移(CLS)0.250.02-92%
速度指数6.82.1-69%

Chrome DevTools对比

Performance面板:

优化前:
├─ Scripting: 4,230ms (红色)
├─ Rendering: 2,150ms (红色)
├─ Painting: 1,890ms (红色)
└─ System: 850ms
Total: 9,120ms

优化后:
├─ Scripting: 320ms (绿色)
├─ Rendering: 180ms (绿色)
├─ Painting: 120ms (绿色)
└─ System: 95ms
Total: 715ms

改善: 92%

Memory面板:

优化前:
├─ Initial: 45MB
├─ 浏览20页: 350MB
├─ DOM Nodes: 12,000
└─ Event Listeners: 850

优化后:
├─ Initial: 35MB
├─ 浏览20页: 48MB
├─ DOM Nodes: 1,800
└─ Event Listeners: 120

改善: 86%

真实用户监控(RUM)数据

部署1个月后收集的数据:

用户性能体验:
├─ 95th percentile LCP: 2.3s (目标 < 2.5s) ✓
├─ 95th percentile FID: 78ms (目标 < 100ms) ✓
├─ 95th percentile CLS: 0.08 (目标 < 0.1) ✓
├─ 跳出率: 35% → 22% (-37%)
├─ 平均停留时间: 2:45 → 4:12 (+53%)
└─ 转化率: 2.1% → 3.8% (+81%)

业务影响:
├─ 页面加载时间减少: 77%
├─ 服务器成本降低: 45% (更少的重试请求)
├─ 用户满意度提升: 65%
└─ 收入增加: 25% (转化率提升)

第六阶段:总结和最佳实践

完成的优化清单

## 优化项目清单

### ✅ Phase 1: 核心优化
- [x] ProductList组件 - 使用useMemo缓存计算
- [x] ProductCard - 实现React.memo
- [x] 列表虚拟化 (react-window)
- [x] 价格计算优化

### ✅ Phase 2: 数据优化
- [x] 实现localStorage缓存
- [x] 添加请求去重
- [x] 实现乐观更新
- [x] 错误重试机制

### ✅ Phase 3: 内存优化
- [x] 修复定时器泄漏
- [x] 修复事件监听器泄漏
- [x] 修复WebSocket泄漏
- [x] 添加AbortController清理

### ✅ Phase 4: 监控和测试
- [x] 集成Web Vitals
- [x] 创建性能监控面板
- [x] 编写性能测试
- [x] 建立性能基准

### ✅ Phase 5: 其他优化
- [x] 图片懒加载
- [x] 代码分割(React.lazy)
- [x] CSS优化(PurgeCSS)
- [x] Gzip压缩

性能优化最佳实践

1. 渲染优化

// ✅ 使用React.memo避免不必要的重新渲染
export const MyComponent = React.memo<Props>((props) => {
// 组件逻辑
}, (prevProps, nextProps) => {
// 自定义比较逻辑
return prevProps.id === nextProps.id;
});

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

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

2. 列表优化

// ✅ 使用虚拟化处理长列表
import { FixedSizeList } from 'react-window';

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

// ✅ 使用稳定的key
{items.map(item => (
<div key={item.id}> {/* ✓ 使用唯一ID */}
{item.name}
</div>
))}

3. 内存管理

// ✅ 总是清理副作用
useEffect(() => {
const timer = setTimeout(() => {}, 1000);
const subscription = subscribe();

return () => {
clearTimeout(timer);
subscription.unsubscribe();
};
}, []);

// ✅ 取消pending请求
useEffect(() => {
const abortController = new AbortController();

fetchData({ signal: abortController.signal });

return () => {
abortController.abort();
};
}, []);

4. 代码分割

// ✅ 使用React.lazy延迟加载
const ProductDetail = React.lazy(() => import('./pages/ProductDetail'));

<Suspense fallback={<Spinner />}>
<ProductDetail />
</Suspense>

5. 性能监控

// ✅ 监控Core Web Vitals
import { getCLS, getFID, getLCP } from 'web-vitals';

getCLS(console.log);
getFID(console.log);
getLCP(console.log);

// ✅ 使用React DevTools Profiler
<Profiler id="MyComponent" onRender={onRenderCallback}>
<MyComponent />
</Profiler>

常见性能陷阱

## 避免这些常见错误

### ❌ 陷阱1: 在render中创建对象/数组
{items.map(item => (
<ProductCard
key={item.id}
style={{ margin: 10 }} // ❌ 每次render创建新对象
options={['a', 'b']} // ❌ 每次render创建新数组
/>
))}

### ✅ 正确做法: 移到const或useMemo
const cardStyle = { margin: 10 };
const cardOptions = ['a', 'b'];

{items.map(item => (
<ProductCard
key={item.id}
style={cardStyle}
options={cardOptions}
/>
))}

### ❌ 陷阱2: 不恰当的useEffect依赖
useEffect(() => {
fetchProducts(category);
}, []); // ❌ 缺少category依赖

### ✅ 正确做法: 包含所有依赖
useEffect(() => {
fetchProducts(category);
}, [category]);

### ❌ 陷阱3: 过早优化
// 为100个商品实现虚拟化 (过度优化)
if (products.length > 100) {
return <VirtualizedList />;
}

### ✅ 正确做法: 根据实际情况优化
// 只在确实需要时才优化
if (products.length > 1000) {
return <VirtualizedList />;
}

性能优化工作流

## 性能优化标准流程

### 1. 测量
- 使用Lighthouse建立基线
- 使用Chrome DevTools Profile识别瓶颈
- 使用React DevTools Profiler找出慢组件
- 收集真实用户监控数据

### 2. 分析
- 识别最严重的性能问题(二八定律)
- 确定优化优先级
- 估算优化投入和收益

### 3. 优化
- 从影响最大的问题开始
- 一次优化一个问题
- 保持代码可读性和可维护性

### 4. 验证
- 重新运行性能测试
- 对比优化前后的数据
- 确保没有引入新问题

### 5. 监控
- 在生产环境持续监控
- 设置性能预算
- 定期审查性能指标

### 6. 迭代
- 根据监控数据调整优化策略
- 持续改进性能
- 保持与业务需求的平衡

Claude Code在性能优化中的价值

## Claude Code如何加速性能优化

### 传统性能优化流程
├─ 手动分析代码: 2-4小时
├─ 识别性能问题: 1-2小时
├─ 编写优化代码: 3-5小时
├─ 测试和调试: 2-3小时
└─ 总计: 8-14小时

### 使用Claude Code
├─ 自动分析代码: 5-10分钟
├─ 智能识别问题: 2-5分钟
├─ 生成优化代码: 10-20分钟
├─ 自动化测试: 5-10分钟
└─ 总计: 30-60分钟

### 效率提升: 10-15倍

### Claude Code的优势
1. **快速识别**: 智能分析代码,自动识别性能反模式
2. **并行分析**: 同时检查多个文件,全面评估性能
3. **智能建议**: 基于最佳实践提供优化建议
4. **代码生成**: 自动生成优化后的代码
5. **测试生成**: 创建性能测试验证优化效果
6. **文档生成**: 自动生成绩效报告和文档

常见问题解答

Q1: 如何判断何时需要优化?

A: 遵循"过早优化是万恶之源"原则:

## 优化时机判断

### 不需要优化的情况:
- 组件渲染时间 < 16ms (60fps)
- 列表项 < 100个
- 用户没有反馈性能问题
- Lighthouse分数 > 90

### 需要优化的情况:
- 用户明确反馈卡顿
- Lighthouse分数 < 50
- 组件渲染时间 > 100ms
- 列表项 > 500个
- 内存持续增长
- CPU使用率长期 > 80%

Q2: 虚拟化一定会提升性能吗?

A: 不一定:

## 虚拟化适用场景

### ✅ 适合虚拟化:
- 列表项 > 500个
- 列表项高度固定或可预测
- 需要频繁滚动
- 单个组件渲染较慢

### ❌ 不适合虚拟化:
- 列表项 < 100个 (反而增加复杂度)
- 列表项高度差异巨大
- 很少滚动
- 单个组件渲染很快 (<1ms)

Q3: React.memo会不会滥用?

A: 会:

## React.memo使用指南

### ✅ 应该使用:
- 组件渲染开销大 (>10ms)
- 经常使用相同的props重新渲染
- 纯展示组件,不依赖外部状态

### ❌ 不应该使用:
- 轻量级组件 (<1ms)
- props频繁改变
- 有内部状态且经常更新
- 每次渲染都不同

### 最佳实践:
先测量,再优化。不要盲目memo所有组件。

Q4: 如何平衡性能和代码可读性?

A:

## 性能 vs 可读性

### 原则:
1. **可读性优先**: 在性能足够好的情况下,优先考虑可读性
2. **渐进优化**: 先写清晰代码,发现瓶颈再优化
3. **注释说明**: 复杂优化必须添加详细注释
4. **提取函数**: 将优化逻辑封装到独立函数

### 示例:

// ❌ 过度优化,难以理解
const d= useMemo(()=>c.reduce((a,b)=>a+(b.p*(1-b.d/100)),0),[c])

// ✅ 优化但可读
const totalPrice = useMemo(() => {
return products.reduce((sum, product) => {
const discount = product.price * (product.discount / 100);
return sum + (product.price - discount);
}, 0);
}, [products]);

Q5: 如何追踪优化效果?

A: 建立完整的性能监控系统:

// 性能追踪示例
import { trackPerformance } from './analytics';

export const usePerformanceTracking = (operationName: string) => {
return useCallback(async <T>(
operation: () => Promise<T>
): Promise<T> => {
const startTime = performance.now();

try {
const result = await operation();

const endTime = performance.now();
const duration = endTime - startTime;

// 发送到分析服务
trackPerformance({
name: operationName,
duration,
success: true,
});

return result;
} catch (error) {
const endTime = performance.now();
const duration = endTime - startTime;

trackPerformance({
name: operationName,
duration,
success: false,
error: error instanceof Error ? error.message : 'Unknown',
});

throw error;
}
}, [operationName]);
};

// 使用
const trackRender = usePerformanceTracking('ProductList-render');
await trackRender(() => renderProducts());

总结

关键成果

性能提升3-5倍

  • Lighthouse: 32 → 94 (+194%)
  • 首屏加载: 8.7s → 2.0s (-77%)
  • 交互响应: 185ms → 42ms (-77%)

用户体验改善

  • 跳出率 -37%
  • 停留时间 +53%
  • 转化率 +81%

技术债务减少

  • 修复10+内存泄漏
  • 代码可维护性提升
  • 建立性能监控体系

学到什么

  1. 系统化分析方法

    • Lighthouse建立基线
    • DevTools定位瓶颈
    • Profiler分析组件
  2. 针对性优化策略

    • 渲染优化(memo、useMemo、useCallback)
    • 列表优化(虚拟化)
    • 内存管理(清理副作用)
    • 数据优化(缓存、去重)
  3. 性能监控和测试

    • 集成Web Vitals
    • 编写性能测试
    • 建立监控体系
  4. Claude Code加速

    • 自动分析问题
    • 生成优化代码
    • 创建测试用例
    • 效率提升10-15倍

下一步优化

进阶方向

  • 服务端渲染(Next.js SSR)
  • 边缘缓存(Cloudflare Workers)
  • Web Workers(计算密集任务)
  • PWA(离线功能)
  • 性能预算自动化(CI/CD集成)

性能优化是持续过程,不是一次性任务。Claude Code帮你更高效识别和解决问题。

完整项目结构

ecommerce-app-optimized/
├── src/
│ ├── components/
│ │ ├── ProductList.tsx # ✓ useMemo优化
│ │ ├── ProductCard.tsx # ✓ React.memo
│ │ ├── VirtualProductList.tsx # ✓ 新增虚拟化
│ │ ├── SearchBar.tsx # ✓ 防抖
│ │ ├── FilterSidebar.tsx # ✓ 修复内存泄漏
│ │ └── PerformanceDashboard.tsx # ✓ 新增监控
│ ├── hooks/
│ │ ├── useProducts.ts # ✓ 缓存和重试
│ │ ├── usePerformanceMonitor.ts # ✓ 新增
│ │ └── useVirtualList.ts # ✓ 新增
│ ├── __tests__/
│ │ └── performance/
│ └── utils/
│ └── performance.ts # ✓ 新增
├── package.json # ✓ web-vitals
└── PERFORMANCE.md # ✓ 优化文档

参考资源

官方文档

推荐工具

相关文章


下一步

  1. 给项目跑Lighthouse
  2. 用Claude Code分析瓶颈
  3. 实施Phase 1优化
  4. 建立监控体系
  5. 持续迭代