LoginSignup
4
4

More than 1 year has passed since last update.

React Nativeパフォーマンス最適化のポイントまとめ

Posted at

React Nativeでパフォーマンスを向上するためのポイントについてまとめました。

ScrollViewではなく、FlatListを使用

 表示するデータ量が多い場合は、ScrollViewではなくFlatListを使用しましょう。

 ScrollViewは一度に全ての子コンポーネントをレンダリングします。見えていない箇所の子コンポーネントとレンダリングされるためメモリ使用量が増えます。

ScrollViewでの実装

const data = [
  {
    text: "1",
  },
  {
    text: "2",
  },
]

const App = () => (
  <ScrollView>
    {data.map((_) => (
      <Text>{_}</Text>
    ))}
  </ScrollView>
)

 一方、FlatListは画面に見えている箇所のみレンダリングし、画面から見えなくなるとレンダリングを止めます。メモリ使用量を抑えるには、ScrollViewよりFlatListが良いと言えます。

const data = [
  {
    text: "1",
  },
  {
    text: "2",
  },
]

const App = () => (
  <FlatList
    data={data} 
    renderItem={({ item }) => (
      <Text>{item.text}</Text>
    )}
  />
)

本番環境でconsole.*を実行させない

 console.logconsole.warnはデバッグに用いることが多いでしょう。ただ、本番環境ではconsole.*は不要なので実行させないようにしましょう。 
yarn add -D babel-plugin-transform-remove-consoleでプラグインをインストールし、babel.config.jsを修正します。

babel.config.js

module.exports = function (api) {
  const babelEnv = api.env();
  const plugins = [];
  if (babelEnv !== "development") {
    plugins.push(["transform-remove-console", { exclude: ["error"] }]);
  }
  return {
    presets: [...],
    plugins
  };
};

画像のファイル形式を変える

 画像のファイル形式でもパフォーマンスに差が出てきます。よく使われるのはJPEGPNGですが、PNG形式の画像だと色数を減らしてファイルサイズを落とすことができます。JPEGよりPNGの方がパフォーマンス最適化には優れているといえるでしょう。
PNGより優れたパフォーマンスを発揮するものとして、WebPがあります。ただ、WebPはスマホのosのバージョンによってはサポートされていなかったりします。

react-native-fast-imageを使う

 react-nativeに組み込まれているImageコンポーネントは時に表示が遅く感じることがあります。この問題の解決策としてのおすすめはreact-native-fast-imageを使うことです。組み込みのImageコンポーネントとほとんど同じように使うことができ、画像のちらつきや低パフォーマンスの改善が可能になります。
https://www.npmjs.com/package/react-native-fast-image

Imageコンポーネント

import Image from 'react-native'

const YourImage = () => (
    <Image
        source={{
            uri: '...'
        }}
    />
)

react-native-fast-image

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

const YourImage = () => (
    <Image
        source={{
            uri: '...'
        }}
    />
)

useNativeDriverを設定

react-nativeのアニメーションは何も設定しなければ、アニメーションのJSスレッドで実行されます。もし、JSスレッドがスタックしていた場合アニメーションフレームはスキップされます。これを解決するのがuseNativeDriverです。
参考↓
https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated

Animated.timing(this.state.animatedValue, {
  toValue: 1,
  duration: 500,
  useNativeDriver: true, 
}).start();

hermesを使用

hermes(エルメス)はReact Nativeを拘束に実行するために作られたJSエンジンです。
React NativeのbareworkFlowを使っている場合とexpoを使用している場合で設定方法が変わります。

androidの設定

android/app/build.gradle

  project.ext.react = [
      entryFile: "index.js",
-     enableHermes: false  // clean and rebuild if changing
+     enableHermes: true  // clean and rebuild if changing
  ]
$ cd android && ./gradlew clean

iosの設定

ios/Podfile

   use_react_native!(
     :path => config[:reactNativePath],
     # to enable hermes on iOS, change `false` to `true` and then install pods
-    :hermes_enabled => false
+    :hermes_enabled => true
   )
cd ios && pod install

expoの設定

app.json

{
  "expo": {
    "android": {
      "jsEngine": "hermes"
    }
  }
}

expoでhermesを使う注意点として、2021年8月24日現在ではandroidのみかつ、EAS(expo application service) buildのみでしかビルドできません。
EAS buildは有料で月$29かかります。
https://expo.dev/pricing
ただ、ビルドさえしてしまうとOTAアップデートもいつも通りできます。

最後に

随時更新して情報を追加していきます。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4