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.log
やconsole.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
};
};
画像のファイル形式を変える
画像のファイル形式でもパフォーマンスに差が出てきます。よく使われるのはJPEG
とPNG
ですが、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アップデートもいつも通りできます。
最後に
随時更新して情報を追加していきます。