目录

  1. 1. 渲染性能优化

  2. 2. 列表性能优化

  3. 3. 图片优化

  4. 4. 内存优化

  5. 5. 启动优化

  6. 6. 网络优化

  7. 7. 调试工具

  8. 8. 原生模块优化

  9. 9. 性能检查清单

  10. 10. 实战案例

一、渲染性能优化 1.1 使用React.memo避免不必要的重渲染

// ❌ 低效:父组件更新时子组件总是重渲染
const UserProfile = ({ user, onEdit }) => {
return (
{user.name} Text>
View>
);
};

// ✅ 优化:使用 React.memo 缓存组件
const UserProfile = React.memo(({ user, onEdit }) => {
return (
{user.name} Text>
View>
);
});

// 配合 useMemo 缓存回调函数
const handleEdit = useCallback(() => {
// 处理逻辑
}, []);

1.2 使用useMemouseCallback

// ❌ 低效:每次渲染都创建新对象和函数
const TodoList = ({ todos }) => {
const filteredTodos = todos.filter(t => t.completed);
const handlePress = () => console.log('pressed');
return filteredTodos.map(todo => (
));
};


// ✅ 优化:缓存计算结果和回调
const TodoList = React.memo(({ todos }) => {
const filteredTodos = useMemo(
() => todos.filter(t => t.completed),
[todos]
);
const handlePress = useCallback(() => {
console.log('pressed');
}, []);
return filteredTodos.map(todo => (
));
});
1.3 避免内联样式和对象

// ❌ 低效:每次渲染创建新对象
const Text = () => ;


// ✅ 优化:使用 StyleSheet
const styles = StyleSheet.create({
container: { padding: 10, margin: 5 }
});
const Text = () => ;
1.4 使用key优化列表渲染

// ❌ 低效:使用 index 作为 key
{items.map((item, index) => (
))}


// ✅ 优化:使用唯一 ID 作为 key
{items.map(item => (
))}
二、列表性能优化 2.1 使用FlatList替代ScrollView

// ❌ 低效:渲染所有项目
{items.map(item => )}
ScrollView>


// ✅ 优化:虚拟列表,只渲染可见区域
data={items}
renderItem={({ item }) => }
keyExtractor={item => item.id}
// 关键优化参数
initialNumToRender={10} // 初始渲染数量
maxToRenderPerBatch={10} // 每批渲染数量
windowSize={5} // 渲染窗口大小
removeClippedSubviews={true} // 移除屏幕外子视图
updateCellsBatchingPeriod={100} // 批量更新间隔
/>
2.2 实现getItemLayout跳过测量

const ITEM_HEIGHT = 80;


data={items}
renderItem={renderItem}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
2.3 使用React.memo优化列表项

const ListItem = React.memo(({ item, onPress }) => {
return (
onPress(item)}>
{item.title} Text>
TouchableOpacity>
);
}, (prevProps, nextProps) => {
// 自定义比较函数
return prevProps.item.id === nextProps.item.id;
});
2.4 使用SectionList优化分组列表

  sections={sections}
keyExtractor={item => item.id}
renderItem={({ item }) => }
renderSectionHeader={({ section }) => }
// 优化参数
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews={true}
/>
2.5 长列表优化技巧

// 使用 getItemLayout 避免测量
const getItemLayout = (data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
});

// 使用 extraData 避免不必要的重渲染
data={items}
extraData={selectedId}
renderItem={renderItem}
getItemLayout={getItemLayout}
/>

// 使用 CellRendererComponent 自定义渲染
data={items}
CellRendererComponent={React.memo(({ children, ...props }) => (
{children} View>
))}
/>
三、图片优化 3.1 使用合适的图片格式和尺寸

// ✅ 使用 WebP 格式(更小体积)


// ✅ 根据设备像素比加载合适尺寸
const scale = PixelRatio.getPixelSizeForLayoutSize(1);
const uri = `image_${width * scale}x${height * scale}.webp`;

// ✅ 使用缓存
source={{ uri }}
cache="immutable" // 或 "web-only", "cache-only"
/>
3.2 使用react-native-fast-image

npm install react-native-fast-image

import FastImage from 'react-native-fast-image';



source={{
uri: 'https://example.com/image.jpg',
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable,
}}
resizeMode={FastImage.resizeMode.cover}
/>
3.3 图片懒加载

import FastImage from 'react-native-fast-image';


data={images}
renderItem={({ item }) => (
source={{ uri: item.uri }}
// 仅在可见时加载
/>
)}
/>
3.4 图片预加载

import FastImage from 'react-native-fast-image';

// 预加载图片
FastImage.preload([
{ uri: 'https://example.com/image1.jpg' },
{ uri: 'https://example.com/image2.jpg' },
]);

// 在列表中预加载下一批图片
const loadNextImages = (currentIndex: number) => {
const nextImages = images.slice(currentIndex + 5, currentIndex + 10);
FastImage.preload(nextImages.map(img => ({ uri: img.url })));
};
3.5 图片压缩

# 使用 imagemin 压缩图片
npm install -g imagemin-cli
imagemin images/* --out-dir=dist --plugin=webp --quality=80
四、内存优化 4.1 避免内存泄漏

// ✅ 正确清理订阅和定时器
useEffect(() => {
const timer = setInterval(() => {}, 1000);
const subscription = eventEmitter.addListener('event', handler);
return () => {
clearInterval(timer);
subscription.remove();
};
}, []);


// ✅ 清理异步请求
useEffect(() => {
let cancelled = false;
const loadData = async () => {
const result = await fetchData();
if (!cancelled) {
setData(result);
}
};
loadData();
return () => {
cancelled = true;
};
}, []);
4.2 使用InteractionManager延迟执行

import { InteractionManager } from 'react-native';


// 在动画和交互完成后执行
useEffect(() => {
const task = InteractionManager.runAfterInteractions(() => {
// 执行耗时操作
loadLargeData();
});
return () => task.cancel();
}, []);
4.3 避免大对象持有

// ❌ 低效:大对象一直持有
const [data, setData] = useState(largeData);

// ✅ 优化:按需加载,及时清理
const loadData = async () => {
const result = await fetchLargeData();
setData(result);
};

const clearData = () => {
setData(null);
// 触发 GC
};
4.4 使用useRef避免不必要的重渲染

// ❌ 低效:state 变化触发重渲染
const [count, setCount] = useState(0);


// ✅ 优化:ref 变化不触发重渲染
const countRef = useRef(0);
countRef.current = count;
4.5 清理事件监听器

useEffect(() => {
const handleOrientationChange = () => {
// 处理方向变化
};
Dimensions.addEventListener('change', handleOrientationChange);
return () => {
Dimensions.removeEventListener('change', handleOrientationChange);
};
}, []);
五、启动优化 5.1 减少初始加载内容

// ✅ 分屏加载
const App = () => {
const [isReady, setIsReady] = useState(false);
useEffect(() => {
// 先显示启动屏
InteractionManager.runAfterInteractions(() => {
// 后台加载数据
preloadData().then(() => setIsReady(true));
});
}, []);
if (!isReady) return ;
return ;
};
5.2 使用 Hermes 引擎

// android/app/build.gradle
project.ext.react = [
enableHermes: true // 启用 Hermes
]


// iOS/Podfile
hermes_enabled = true
5.3 减少包体积

# 分析包体积
npx react-native-bundle-visualizer

# 移除未使用的依赖
npx depcheck

# 生产环境移除 console
// babel.config.js
plugins: [
process.env.NODE_ENV === 'production' && [
'transform-remove-console',
{ exclude: ['error', 'warn'] }
]
]
5.4 代码分割

// 使用动态导入
const HeavyComponent = lazy(() => import('./HeavyComponent'));


// 使用时
}>
Suspense>
5.5 预加载关键资源

// 预加载字体
useFonts({
'Inter-Regular': require('./assets/fonts/Inter-Regular.ttf'),
});


// 预加载图片
const images = {
logo: require('./assets/logo.png'),
background: require('./assets/bg.png'),
};
六、网络优化 6.1 请求缓存

const cache = new Map();


const fetchWithCache = async (url, ttl = 5 * 60 * 1000) => {
const cached = cache.get(url);
if (cached && Date.now() - cached.timestamp < ttl) {
return cached.data;
}
const response = await fetch(url);
const data = await response.json();
cache.set(url, { data, timestamp: Date.now() });
return data;
};
6.2 请求合并与防抖

// 防抖搜索
const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
};


// 使用
const searchQuery = useDebounce(query, 300);
6.3 请求节流

const useThrottle = (value, interval) => {
const [throttledValue, setThrottledValue] = useState(value);
const lastUpdated = useRef(Date.now());
useEffect(() => {
const now = Date.now();
if (now - lastUpdated.current >= interval) {
setThrottledValue(value);
lastUpdated.current = now;
} else {
const timer = setTimeout(() => {
setThrottledValue(value);
lastUpdated.current = Date.now();
}, interval - (now - lastUpdated.current));
return () => clearTimeout(timer);
}
}, [value, interval]);
return throttledValue;
};
6.4 使用react-query管理服务器状态

npm install @tanstack/react-query

import { useQuery, useMutation, QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 分钟
cacheTime: 10 * 60 * 1000, // 10 分钟
retry: 3,
},
},
});

// 使用
const { data, isLoading, error } = useQuery({
queryKey: ['users', userId],
queryFn: () => fetchUser(userId),
});

// 预取数据
queryClient.prefetchQuery({
queryKey: ['users', nextUserId],
queryFn: () => fetchUser(nextUserId),
});
6.5 批量请求

// 使用 Promise.all 并行请求
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments(),
]);


// 使用 Promise.allSettled 处理部分失败
const results = await Promise.allSettled([
fetchUsers(),
fetchPosts(),
fetchComments(),
]);
七、调试工具 7.1 Flipper 性能监控

# 安装 Flipper
npm install react-native-flipper


# 插件
- React DevTools
- Network Inspector
- Layout Inspector
- Hermes Debugger
- React Native Performance
7.2 性能监控代码

import { Performance } from 'react-native';

// 测量渲染时间
const measureRender = (componentName: string) => {
const mark = `__${componentName}_start`;
Performance.mark(mark);
return () => {
Performance.measure(componentName, mark);
Performance.clearMarks(mark);
};
};

// 使用
useEffect(() => {
const endMeasure = measureRender('HomeScreen');
return endMeasure;
}, []);
7.3 FPS 监控

import { requestAnimationFrame } from 'react-native';

let frameCount = 0;
let lastTime = Date.now();

const monitorFPS = () => {
frameCount++;
const now = Date.now();
if (now - lastTime >= 1000) {
console.log(`FPS: ${frameCount}`);
frameCount = 0;
lastTime = now;
}
requestAnimationFrame(monitorFPS);
};
7.4 使用why-did-you-render检测不必要的重渲染

npm install @welldone-software/why-did-you-render

// index.js
import whyDidYouRender from '@welldone-software/why-did-you-render';
import React from 'react';


if (__DEV__) {
whyDidYouRender(React, {
trackAllPureComponents: true,
});
}
7.5 使用 React DevTools Profiler

import { Profiler } from 'react';

const onRenderCallback = (
id,
phase,
actualDuration,
baseDuration,
startTime,
commitTime
) => {
console.log(`${id} 渲染耗时: ${actualDuration}ms`);
};


Profiler>
八、原生模块优化 8.1 使用 TurboModules 和 Fabric

// 新架构启用
// android/gradle.properties
newArchEnabled=true


// ios/Podfile
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
8.2 原生模块异步调用

// 避免阻塞 JS 线程
NativeModule.heavyTask(params)
.then(result => {
// 处理结果
})
.catch(error => {
// 处理错误
});
8.3 使用 JSI 直接调用原生代码

// 通过 JSI 直接调用,避免桥接开销
global.nativeCallSync = (arg) => {
return someNativeFunction(arg);
};


// 同步调用,无桥接延迟
const result = global.nativeCallSync(data);
8.4 原生动画优化

// 使用 react-native-reanimated 运行在 UI 线程
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';

const offset = useSharedValue(0);

const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ translateY: offset.value }],
};
});

// 驱动动画
offset.value = withSpring(100);
九、性能检查清单

优化项

检查方法

目标

渲染帧率

Flipper FPS Monitor

≥ 55 FPS

列表滚动

长列表测试

无卡顿

内存使用

Xcode/Android Profiler

无泄漏

启动时间

adb shell am start -W

< 2s

包体积

npx react-native-bundle-visualizer

iOS < 100MB

网络请求

Network Inspector

减少重复请求

图片大小

检查图片资源

WebP + 合适尺寸

JS 包大小

npx react-native-bundle-visualizer

< 5MB

内存泄漏

LeakCanary/Instruments

无泄漏

冷启动时间

Time to Interactive

< 2s

9.1 Android 性能检查

# 检查启动时间
adb shell am start -W com.yourapp/.MainActivity

# 检查内存
adb shell dumpsys meminfo com.yourapp

# 检查 GPU 渲染
adb shell dumpsys gfxinfo com.yourapp
9.2 iOS 性能检查

# 使用 Instruments 检查
open -a Instruments


# 检查工具
- Time Profiler
- Allocations
- Leaks
- Energy Log
9.3 自动化性能测试

// 使用 detox 进行性能测试
describe('Performance', () => {
it('should scroll list smoothly', async () => {
await element(by.id('flatList')).swipe('up', 'fast', 0.5);
// 检查 FPS
});
it('should load within 2 seconds', async () => {
const startTime = Date.now();
await waitFor(element(by.id('homeScreen'))).toBeVisible().withTimeout(2000);
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(2000);
});
});
十、实战案例 10.1 优化前 vs 优化后

// ❌ 优化前:60 FPS → 30 FPS
const Feed = ({ posts }) => {
return (
{posts.map(post => (
key={post.id}
post={post}
onPress={() => navigation.navigate('Detail', { post })}
/>
))}
ScrollView>
);
};

// ✅ 优化后:稳定 60 FPS
const PostCard = React.memo(({ post, onPress }) => {
const handlePress = useCallback(() => onPress(post), [post, onPress]);
return (

{post.title} Text>
TouchableOpacity>
);
});

const Feed = ({ posts }) => {
const navigation = useNavigation();
const handleNavigate = useCallback((post) => {
navigation.navigate('Detail', { post });
}, [navigation]);
return (
data={posts}
renderItem={({ item }) => (
)}
keyExtractor={item => item.id}
initialNumToRender={5}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews={true}
getItemLayout={(data, index) => ({
length: 200,
offset: 200 * index,
index,
})}
/>
);
};
10.2 电商列表页优化

// 优化要点:
// 1. FlatList 虚拟列表
// 2. React.memo 缓存商品卡片
// 3. FastImage 图片缓存
// 4. getItemLayout 跳过测量
// 5. 下拉刷新 + 上拉加载

const ProductCard = React.memo(({ product, onPress }) => {
const handlePress = useCallback(() => onPress(product), [product, onPress]);
return (
source={{
uri: product.image,
priority: FastImage.priority.normal,
}}
resizeMode={FastImage.resizeMode.cover}
/>
{product.name} Text>
¥{product.price} Text>
TouchableOpacity>
);
});

const ProductList = () => {
const [page, setPage] = useState(1);
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);
const loadProducts = async (pageNum: number) => {
if (loading) return;
setLoading(true);
try {
const data = await fetchProducts(pageNum);
setProducts(prev => pageNum === 1 ? data : [...prev, ...data]);
} finally {
setLoading(false);
}
};
const handleLoadMore = () => {
if (!loading) {
setPage(prev => prev + 1);
loadProducts(page + 1);
}
};
return (
data={products}
numColumns={2}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => (
product={item}
onPress={product => navigation.navigate('Detail', { product })}
/>
)}
onRefresh={() => {
setPage(1);
loadProducts(1);
}}
refreshing={loading && page === 1}
onEndReached={handleLoadMore}
onEndReachedThreshold={0.3}
initialNumToRender={10}
maxToRenderPerBatch={20}
windowSize={5}
removeClippedSubviews={true}
getItemLayout={(data, index) => ({
length: 280,
offset: 280 * index,
index,
})}
ListFooterComponent={loading ? : null}
/>
);
};
10.3 聊天列表优化

// 消息列表优化:
// 1. 倒序显示最新消息
// 2. 自动滚动到底部
// 3. 图片消息懒加载
// 4. 消息气泡复用

const MessageItem = React.memo(({ message, onAvatarPress }) => {
const isMe = message.senderId === currentUserId;
return (
{!isMe && (
onAvatarPress(message.sender)}>
source={{ uri: message.senderAvatar }}
/>
TouchableOpacity>
)}

{message.type === 'image' ? (
source={{ uri: message.content }}
resizeMode={FastImage.resizeMode.cover}
/>
) : (
{message.content} Text>
)}
{formatTime(message.createdAt)} Text>
View>
View>
);
});

const ChatList = ({ chatId }) => {
const [messages, setMessages] = useState([]);
const flatListRef = useRef(null);
// 订阅新消息
useEffect(() => {
const subscription = messageService.subscribe(chatId, (newMessage) => {
setMessages(prev => [...prev, newMessage]);
// 自动滚动到底部
InteractionManager.runAfterInteractions(() => {
flatListRef.current?.scrollToEnd({ animated: true });
});
});
return () => subscription.remove();
}, [chatId]);
// 加载历史消息
const loadHistory = async () => {
const history = await messageService.getHistory(chatId);
setMessages(history);
};
useEffect(() => {
loadHistory();
}, [chatId]);
return (
ref={flatListRef}
data={messages}
inverted // 倒序显示
keyExtractor={item => item.id}
renderItem={({ item }) => (
message={item}
onAvatarPress={sender => navigation.navigate('Profile', { sender })}
/>
)}
onEndReached={loadMoreHistory}
onEndReachedThreshold={0.5}
initialNumToRender={20}
maxToRenderPerBatch={20}
windowSize={10}
removeClippedSubviews={true}
maintainVisibleContentPosition={{
minIndexForVisible: 0,
}}
/>
);
};
附录:推荐工具和库

类别

工具/库

用途

图片

react-native-fast-image

高性能图片加载

动画

react-native-reanimated

UI 线程动画

状态管理

@tanstack/react-query

服务器状态管理

调试

react-native-flipper

调试工具平台

性能检测

why-did-you-render

重渲染检测

包分析

react-native-bundle-visualizer

包体积分析

测试

detox

E2E 性能测试

监控

sentry-react-native

错误和性能监控

参考资料

  • • React Native 官方文档 - 性能

  • • React Native 性能优化指南

  • • Hermes 引擎文档

  • • Flipper 文档