[譯] React Native性能優化:應該作和不該該作的|技術點評

翻譯原文: React Native Performance: Do and Don’t
做者: amanhimselfjavascript

在使用一些框架例如React Native去實際開發移動端應用的時候,性能是一個重要的問題。React Native默認狀況下的性能是沒有問題的,可是在實際開發React Native的時候,咱們也可能會遇到一些性能相關的問題。java

這些問題是很難經過組件自己修復去解決的。在這篇文章中,咱們會提供一些建議來優化開發React Native遇到的一些性能問題。react

使用Image緩存解決方案

React Native在自帶的組件庫中提供了Image組件,能夠用例展現圖片。可是這個組件沒有解決如下這些問題的開箱即用的解決方案:git

  • 屏幕中渲染大量圖片
  • 通常狀況下性能比較低
  • 從緩存中加載性能比較低
  • 會有加載閃爍

React Native中的Image組件處理緩存圖片的時候會像web 瀏覽器同樣的行爲,會可能致使上面提到的問題。能夠經過使用第三方庫react-native-fast-image來解決上面的這些問題。這個庫在iOS和安卓上均可用而且可以有效的緩存圖片github

使用適當大小的圖片

若是React Native APP依賴於使用大量的圖像,那麼優化圖像對於APP的性能是很重要的。若是圖片的尺寸沒有獲得合適的優化,渲染大量圖片會致使在設備上佔用大量的內存。這可能會致使APP崩潰web

一些能夠在React Native中有效優化圖片的方案包括:數據庫

  • 使用PNG格式的圖片而不是JPG
  • 使用尺寸更小的圖片
  • 使用WEBP格式的圖片。能夠在iOS和Android平臺減小29%的二進制大小。

避免沒必要要的渲染

React Native是基於React的庫而且處理組件渲染的形式相似於React.js。所以在React中可用的優化方法也適用於React Native。一個優化方法就是避免沒必要要的渲染,在函數組件中能夠經過使用React.memo()來完成。json

React.memo是被用來進行處理記憶化(memoization)。記憶化的理念是:若是一個組件接收相同的props超過一次,它將會使用以前一次緩存的props。而且函數組件只會進行一次渲染返回jsxreact-native

例以下面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中使用滾動列表。其中兩種最經常使用的方式就是使用ScrollViewFlatList組件

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 春招闖關活動」, 點擊查看 活動詳情

相關文章
相關標籤/搜索