どれも公式ドキュメントで触れられるくらい大事なことなので、取り組む前に軽く目を通して置くと助けになると思います。
主にメインスレッドに処理を切り分けよう、モニタリングできるようにしよう、起動時のロードを減らそうって内容です。
最終更新日: 2018 6/21
React Nativeに触れる機会が増えているので随時更新していきます。
知っておきたいことまとめ
できる限りメインスレッドに処理を任せる
- JSスレッドとメインスレッド(Nativeのスレッド)が動いておりJSスレッドがボトルネックになることが多い
- 100ms以上フレームが落ちるとユーザーに感じ取られる
- JSスレッドで必要なすべてのコンポーネントをレンダリングするため、Navigatorの遷移中にフレーム落ちが発生しやすい
- JSスレッドが忙しいとメインスレッドから受け取ったタッチイベントに反応できないが、フィードバックは即座に描写してしまう
- NavigatorIOSはアニメーションをメインスレッド上で行うためフレーム落ちを起こさない
- 開発モードではJSスレッドのパフォーマンスが大幅に低下する
- ListViewではなくFlasListにするとパフォーマンスが上がる
- 描写が遅ければgetItemLayouを実装して最適化する
- rowHasChangedを実装することでレンダリングの必要を確認する処理を減らせる
アニメーション
- LayoutAnimationはCore Animationを使うのでJSスレッドのフレーム落ちの影響を受けない
- Viewを動かす処理でフレーム落ちしやすい
- メモリの使用量に気をつける
- アルファ合成等はshouldRasterizeIOSやrenderToHardwareTextureAndroidに任せれるかもしれない
- 画像のサイズをアニメーションするとフレーム落ちしやすい
- onPress関数が返されるまでフィードバックを返せない場合はrequestAnimationFrameでアクションをラップする
handleOnPress() {
// Always use TimerMixin with requestAnimationFrame, setTimeout and
// setInterval
this.requestAnimationFrame(() => {
this.doExpensiveAction();
});
}
- アニメーションの値をリスト化してメインスレッドに送信するとJSスレッドを経由せずフレーム落ちも起きない
プロファイリングでボトルネックを特定する
- ChromeのDedicatedWorker Threadをみてボトルネックを探す
- systraceを使ってAndroidのUIのパフォーマンスをプロファイルする
起動時のロードを減らす
- インラインでrequireすることによって起動時のロードを減らす
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';
let VeryExpensive = null;
export default class Optimized extends Component {
state = { needsExpensive: false };
didPress = () => {
if (VeryExpensive == null) {
VeryExpensive = require('./VeryExpensive').default;
}
this.setState(() => ({
needsExpensive: true,
}));
};
render() {
return (
<View style={{ marginTop: 20 }}>
<TouchableOpacity onPress={this.didPress}>
<Text>Load</Text>
</TouchableOpacity>
{this.state.needsExpensive ? <VeryExpensive /> : null}
</View>
);
}
}