React Native Tech Blog

supported by maricuru (旧maricuru tech blogです)

React Native+Expoなアプリのリリースから1年たって - つらみ編

(本ブログポストは React Native Advent Calendar 2018 の4日目の記事になります。)

弊社ではmaricuruという花嫁さん向けのコミュニティアプリをReact Native + Expoな環境で開発しています。

昨年の12/20にβリリースとしてiOSストア公開したので、もうすぐ1周年ということになります。

1年前はmaricuruというものがこの世に存在しないところから、この1年で多くの花嫁さんに利用いただき、また投資家からもmaricuruを評価いただき春には資金調達に成功しました。
現在は、社名も株式会社maricuruに変更しオフィスも移転するなど、1年前には想像できなかったほどの変化がありました。


そんなmaricuruアプリはReact Native + Expoで開発しており、基本的には
React Nativeはいいぞ、Expoはいいぞ
と言い続けていますが、 良い点については今まで色んな所で書いてきてるので、今回は苦労した点や注意点なつらみを中心に振り返ってみたいと思います。


参考:良い点について過去記事

ExpoでReact Nativeアプリを開発するメリット5選 - maricuru tech blog

React Native + Expoなアプリを リリースして1年を”5分”で振り返る - Speaker Deck

アナリティクス系のSDK

ExpoだとネイティブSDKを自由に組み込めないのは最大のネックですが、中でもアナリティクス系は「これ使えたらいいのにな〜」ってのが結構あります。

例えばFirebase Analytics(今はFirebase向けGoogle Analyticsっていうのかな?)が使えません。

ExpoでFirebase自体は使えますが、Firebase Web SDKを利用する形なので、Web SDKにない機能は使えません。
その使えない機能の一つがAnalyticsということです...

フォーラムでもリクエストが多そうなので、そのうち導入されることを期待しましょう。

Adding react-native-firebase to Expo | Feature Requests | Expo



あとはReproとか。

PMFからグロースまで、かなり使えそうな印象です。
なかでもユーザーのアプリ操作が動画で確認できるのは面白そう。UX改善に役立ちそうです。

先日React Native用のSDKがリリースされたのですが、冒頭で...

react-native init コマンドにより作成されたプロジェクトのみ対応しています。

https://docs.repro.io/ja/dev/sdk/getstarted/react-native.html

とのことでExpoで作ってるアプリには対応してないようでした... 



というツラミはあるものの、maricuruではAmplitudeを使っており、だいぶ使い慣れてきた感もあります。
Expoが公式でサポートしているというのが当初の導入理由ですが、立ち上げ当初は必要な分析環境がスムーズに構築できた印象があります。

【React Native】【Expo】分析ツールAmplitudeの導入方法とそのメリット - maricuru tech blog

またAmplitudeは蓄積したログのエクスポートAPIがあるので、別のDBに蓄積したデータを突っ込むなんてことも可能です。

Amplitudeでは自由にSQLが書けないので、細かい分析をしたいときに歯がゆいこともあります。 そこでmaricuruではそのAmplitudeのデータをBigQueryにエクスポートする基盤を構築して、細かい分析はRedash→BigQuery経由で行えるようにしています。

f:id:wasan:20181203164351p:plain

この辺の詳しい話はまた別の記事で書きたいと思います。

JSバンドルの更新が重い

Expoの最大の利点として、ストア申請なしで中身のJSバンドルだけをOTAアップデートできるという点があります。
ただこのJSバンドルのダウンロードが割と重いことがあります。
社内のWi-Fi環境だと気付かないのですが、実際にユーザーが屋外で使っていると電波状況次第ではストレスフルなレベルで待たされることがありました。

ここに関しては一応対策があります。

デフォルトでは起動時に最新版JSバンドルを落としてきますが、それをManualモードにして自分でハンドリングすればOKです。
例えば以下のような感じで、非同期でJSバンドルを落としてきてユーザーに確認の上で更新するなどすれば、起動時間のストレスは軽減されると思います。

    try {
      const update = await Expo.Updates.checkForUpdateAsync();
      if (update.isAvailable) {
        await Expo.Updates.fetchUpdateAsync();
        Alert.alert(
          '最新版が利用可能です',
          'アプリを再起動して今すぐ更新しますか?「いいえ」を選んだ場合、次回の起動で更新されます。',
          [
            { text: 'いいえ', onPress: () => {}, style: 'cancel' },
            {
              text: 'はい',
              onPress: () => {
                Expo.Updates.reloadFromCache();
              },
            },
          ],
          { cancelable: false }
        );
      }
    } catch (e) {
      // handle error
    }

最新のJSバンドルが落ちてこないことがある

OTAアップデートが便利すぎて、初めの頃はストア申請は全然せずにOTAで更新しまくっていました。

するとある日、あるユーザーのアプリが遥か昔の懐かしすぎるバージョンで動いておりました(汗)

まあこれはよく見るとドキュメントに書いてあるのですが、ネットワークが繋がってなかったり、30秒かかってもJSバンドルのダウンロードが終わらなかったら、ローカルにキャッシュされてるバージョンで起動される仕様になっています。

If there is no network connection available, or it has not finished downloading in 30 seconds, Expo will fall back to loading a cached version of your app, and continue trying to fetch the update in the background (at which point it will be saved into the cache for the next app load).

Configuring OTA Updates - Expo Documentation

ここでさらに注意点は、ストアから落としたばかりで一度もJSバンドルをダウンロードしたことがない場合、ストア申請時(=buildしたとき)のバージョンで起動します。
buildしたときその時のバージョンを内蔵しているのでしょう。

なのでOTAアップデートは便利とはいえ、大きめの機能改修があった際はbuildしてストア申請すべき、ということを学びました。

まとめ

以上、1年を思い出しながらツラミについて振り返りました。
けど基本的には、React Nativeはいいぞ!Expoはいいぞ!ですね。

明日は、@yoshi_kskさんの「任意のReactコンポーネントをReact Nativeで使う方法」になります!