在使用一些框架例如React Native去实际开发移动端应用的时候,性能是一个重要的问题。React Native默认情况下的性能是没有问题的,但是在实际开发React Native的时候,我们也可能会遇到一些性能相关的问题。
这些问题是很难通过组件本身修复去解决的。在这篇文章中,我们会提供一些建议来优化开发React Native遇到的一些性能问题。
使用Image缓存解决方案
React Native在自带的组件库中提供了Image组件,可以用例展示图片。但是这个组件没有解决以下这些问题的开箱即用的解决方案:
- 屏幕中渲染大量图片
- 一般情况下性能比较低
- 从缓存中加载性能比较低
- 会有加载闪烁
React Native中的Image组件处理缓存图片的时候会像web 浏览器一样的行为,会可能导致上面提到的问题。可以通过使用第三方库react-native-fast-image来解决上面的这些问题。这个库在iOS和安卓上都可用并且能够有效的缓存图片
使用适当大小的图片
如果React Native APP依赖于使用大量的图像,那么优化图像对于APP的性能是很重要的。如果图片的尺寸没有得到合适的优化,渲染大量图片会导致在设备上占用大量的内存。这可能会导致APP崩溃
一些可以在React Native中有效优化图片的方案包括:
- 使用PNG格式的图片而不是JPG
- 使用尺寸更小的图片
- 使用WEBP格式的图片。可以在iOS和Android平台减少29%的二进制大小。
避免不必要的渲染
React Native是基于React的库并且处理组件渲染的形式类似于React.js。因此在React中可用的优化方法也适用于React Native。一个优化方法就是避免不必要的渲染,在函数组件中可以通过使用React.memo()
来完成。
React.memo
是被用来进行处理记忆化(memoization)。记忆化的理念是:如果一个组件接收相同的props超过一次,它将会使用之前一次缓存的props。并且函数组件只会进行一次渲染返回jsx
例如下面Parent组件和Child组件的例子。Parent组件有一个count的state变量,每次button点击的时候更新count
当button点击的时候,即使Child组件的props属性text没有改变,每次Parent组件渲染都会造成Child组件的重新渲染。Child组件没有做任何和Parent组件有关的操作而仅仅是展示一些静态文本。这个行为可以通过把Child组件用React.memo()
包着来进行优化
// Parent.js
const Parent = () => {
const [count, setCount] = useState(0);
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button title='Press me' onPress={() => setCount(count + 1)} />
<Child text='Placeholder text' />
</View>
);
};
// Child.js
const Child = React.Memo(({ text }) => {
return <Text>{text}</Text>;
});
Animated库中使用nativeDriver
React Native中有很多方法可以写动画,最常用的方法就是使用Animated库
Animated
Animated会在动画执行之前,通过nativeDriver把动画发送到原生bridge中,这有助于动画独立于被阻塞的JavaScript线程执行,动画会执行比较流畅而不会丢帧
通过设置useNativeDriver的值为true,可以在Animated库中使用nativeDriver。下面的例子就是在ScrollView组件的onScroll事件中使用useNativeDriver
<ScrollView
showsVerticalScrollIndicator={false}
scrollEventThrottle={1}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: animatedValue } } }],
{ useNativeDriver: true }
)}
>
// 组件的内容
</ScrollView>
使用Flipper进行调试
React Native 0.62.0版本介绍了一个新的调试工具Flipper
。 这是一个给iOS、安卓和React Native使用的平台 。它直接集成在原生代码中,并且在React Native中开箱即用。
使用Flipper
调试app不需要远程调试。需要一个本地连接的Metro实例来与React Native应用进行交互。它可通过React DevTools来检查组件树并检查React组件的state和属性。
它使用原生插件生态系统来调试iOS和Android应用程序。这些插件可用于设备日志、崩溃报告、检查网络请求、检查应用程序的本地数据库、检查缓存的图像等。
使用Hermes
Hermes是一个专为移动端应用优化的开源javascript引擎。React Native 0.60.4版本之后,Hermes
在安卓也可用了。这有利于减少app的下载体积(安卓APK)、降低内存消耗和降低APP的可交互时间
在安卓APP中开启Hermes引擎,需要打开build.gradle
并且修改如下:
def enableHermes = project.ext.react.get("enableHermes", true);
自React Native 0.64-rc.0版本后,Hermes也能用于iOS平台。需要打开Podfile
并且修改如下:
use_react_native!(:path => config[:reactNativePath], :hermes_enabled => true
不要在源代码中保留console表达式
在Javascript应用包括React Native应用中,用console.log
调试是最常用的调试方法之一。然而,在构建React Native应用时,将console
语句留在源代码中可能对JavaScript线程造成一些瓶颈。
一个解决方法就是使用babel-plugin-transform-remove-console
删除掉console
语句。在终端通过下面的方法安装
yarn add babel-plugin-transform-remove-console
然后修改 .babelrc
文件如下来删除所有的console
语句
{
"env": {
"production": {
"plugins": ["transform-remove-console"]
}
}
}
不要使用Scrollview渲染一个大列表数据
有一些方法可以在React Native中使用滚动列表。其中两种最常用的方式就是使用ScrollView
和FlatList
组件
ScrollView
用起来很简单,通常用于使用JavaScript的map()
函数遍历一个数组。 例如:
<ScrollView>
{items.map(item => {
return <Item key={item.id.toString()} />;
})}
</ScrollView>
ScrollView
会一次性渲染所有的子组件,在需要渲染的子组件数量不多的时候会比较好用。但在处理大量的数据的时候会影响到APP的性能。
为了解决渲染大量数据的情况,React Native提供了一个FlatList
组件。这个组件能够懒加载子组件列表,这样APP就不会消耗大量的内存
例如:
<FlatList
data={elements}
keyExtractor={item => `${items.id}`}
renderItem={({ item }) => <Item key={item.id.toString()} />}
/>
结论
React Native是一个用于构建跨平台应用的开源框架。它以JavaScript为核心,并调用原生组件来构建移动端界面和功能。它会是一个高性能框架只要注意考虑到性能
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!