iOS・Android

React Native Final Steps

iOS・Android
この記事は約10分で読めます。

はじめに

React Nativeアプリのリリース前にチェックする項目をまとめてみました。
こちらをベースに進めていきます。
React Native Final Steps

console.logの削除

console.logを含むとReact Nativeアプリが遅くなることがあります。
不要なログはすべて削除しておきましょう。
本番環境のビルドからログを削除するので、開発環境に影響はありません。
今まで通りデバッグすることは可能です。
今回は手動での削除ではなく、babelを使った自動削除をしていきます。

npm install babel-plugin-transform-remove-console --save-dev

.babelrcを作成します。

.babelrc

{
  "env": {
    "production": {
      "plugins": ["transform-remove-console"]
    }
  }
}

これでできるはずですが、できない人は以下も試してみてください。

babel.config.js

module.exports = function(api) {
  api.cache(true);
  if (process.env.NODE_ENV === 'production' || process.env.BABEL_ENV === 'production') {
    // 本番環境の設定
    return {
      "presets": ["module:metro-react-native-babel-preset"],
      "plugins": [["transform-remove-console", {"exclude": ["error", "warn", "info"]}]], // 本番環境にはこのプラグインを入れる(本番環境でのみログを削除したいから)
    }
  } else {
    // 開発環境の設定
    return {
      "presets": ["module:metro-react-native-babel-preset"],
    }
  }
}

画像の圧縮

アセットを自動的に最適化するシステムはすでに導入されているかもしれませんが、画像をしぼってリサイズして最適なパッケージサイズにしていきます。
こちらを開いてください。
squoosh.app
ドラッグアンドドロップしてファイル形式をプロジェクトに合うもの変更して、ダウンロードするだけです!!
何%サイズが削減できるかが分かって便利ですね!!
こちらは一括で圧縮できないので、ファイルを1つずつ圧縮していく必要があります。ちょっと面倒ですね。。
JPEG形式であれば「MozJPEG」、PNG形式であれば「OxiPNG」を選択します。
これらは圧縮したJPEEGファイルやPNGファイルの形式です。

Androidパーミッションの削除

デフォルトで設定されているAndroidパーミッションを削除します。
デフォルトで設定されているパーミッションは以下の4つです。

  • Internet — You’ll probably keep this
  • System Alert — Debug mode uses this
  • Read phone state — Not sure why this is on by default
  • Read and Write external storage — You’ll probably keep this
  • Check License — Used for Ads

android/app/src/main/AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="{YOUR_PROJECT_NAME}"
  xmlns:tools="http://schemas.android.com/tools"
  >

    <uses-permission android:name="android.permission.INTERNET" />
    <!-- WarningやCrashをデバッグ時に画面に表示するために取られていたPermission デバックビルドの時には必要だがリリースビルドの時は不要 -->
    <uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <!-- 現在のセルラーネットワーク情報や通話ステータスなどを含む電話の状態への読み取りに必要 デフォルトで入ってしまうが削除しても安全 -->
    <uses-permission tools:node="remove" android:name="android.permission.READ_PHONE_STATE" />
    <!-- 外部ストレージの書き込みに必要なもの デフォルトで入ってしまうが削除しても安全 -->
    <uses-permission tools:node="remove" android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 外部ストレージの読み込みに必要なもの デフォルトで入ってしまうが削除しても安全 -->
    <uses-permission tools:node="remove" android:name="android.permission.READ_EXTERNAL_STORAGE" />

Android用ProGuardとHermesのチェック

ProGuard

ProGuardを有効にすることで、Androidビルドを最適化、難読化、縮小することができます。自動テストを実行して問題がないかチェックする必要があります。

android/app/build.gradle

- def enableProguardInReleaseBuilds = false
+ def enableProguardInReleaseBuilds = true
// (中略)
    abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            - universalApk false
            + universalApk true  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }

android/app/proguard-rules.proに以下を追記
※以下記事参照
https://github.com/react-native-svg/react-native-svg/issues/1061
https://developer.android.com/studio/build/shrink-code#keep-code

-keep public class com.horcrux.svg.** {*;}

Hermes

Hermesを有効にすることで、起動時間の改善、メモリ使用量の減少、アプリサイズの縮小につながります。

android/app/build.gradle

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

android/app/proguard-rules.proに以下を追記

-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.jni.** { *; }
$ cd android && ./gradlew clean
$ npx react-native run-android --variant release

※お使いのバージョンによってはProxyのサポートが整っていない場合があります。
issueもまだクローズしていないので、気長に待つしかなさそうです。
Proxy

起動時のパフォーマンスチェック

バンドルサイズの確認

コマンドラインからJavaScriptのバンドルを生成します。

# Generate your Android production bundle (just code no assets)
$ yarn react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./index.android.bundle

# Generate your iOS production bundle (just code no assets)
$ yarn react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ./index.ios.bundle

inlineRequires

アプリの起動速度をあげるためinlineRequiresをtrueにします

metro.config.js

module.exports = MetroConfig.create(evaConfig, {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true, // アプリの起動速度を高めます
      },
    }),
  },
});

iOS任意のURLを無効化

iOS 9では、Appleは、すべての通信をHTTPSで保護することを要求するATS(App Transport Security)を有効にしました。ATS は、最低限のセキュリティ仕様を満たしていない接続をブロックします。デフォルトでは、React Native プロジェクトには例外が組み込まれており、ローカルでバンドルを読み込めるようになっています。
アプリをリリースする準備ができたので、この例外を削除する必要があるでしょう。ルールが少ないほど、App Store の評価を通過する可能性が高くなります。
残念ながら、開発を再開するときには、すべてを元の状態に戻さなければなりません。
(ドキュメント翻訳)
ios/{YOUR_PROJECT_NAME}/info.plist

<dict>
  <key>NSAllowsArbitraryLoads</key>
  <!-- 本番環境はfalseにする(localhostの例外を削除するため) -->
  <false />
  <!-- 開発環境ではここから -->
  <true/>
  <key>NSExceptionDomains</key>
  <dict>
    <key>localhost</key>
    <dict>
      <key>NSExceptionAllowsInsecureHTTPLoads</key>
      <true/>
    </dict>
  </dict>
  <!-- ここまでにする -->
</dict>

最後に

今回は私の環境でやってできなかったことは一部割愛しています。
あくまでパフォーマンスの向上のための最終チェックですので、全てできなくてもいいように感じましたが、できて損はないので知見の共有をしようと思い書いてみました。