React Native: react-native 0.56.0 -> 0.59.2 へのアップグレード作業

  • 大分ハマったので作業内容を整理してメモしました
  • 間違いや、もっと良い方法がありましたらご教示頂きたいです

実施日

  • 2019/03/28

環境

作業概要

  1. package.jsonreact-native のバージョンを 0.59.2 に上げて yarn install

  2. package.jsonreact のバージョンを react-native 0.59.2 の peer dependency のバージョン に上げて yarn install

  3. react-native 0.56.0 <-> 0.59.2 間のテンプレート差分 を rn-diff-purge で確認し、必要な差分を手動で取り込む

  4. 0.56.0 -> 0.57.0 へのアップグレードで Manual Upgrades が必要らしいので、 3. の作業に加えて必要な差分があれば取り込む

  5. ビルドが成功するまで、発生するエラーを個別に解消

    • 主な内容: 3. の作業ミス、漏れの修正
  6. アプリが立ち上がったら、ワーニングを個別に解消

    • 主な内容: 関連ライブラリのバージョンアップ
  7. 実機テスト

備考

  • 以前は react-native-git-upgrade を使う方法が公式で推奨されていたが、現時点(2019/03/28)では非推奨となっていた

  • 現時点では、react-native upgrade を使う方法が推奨されている

  • しかし、今回の作業では react-native upgrade を使用しなかった

    • 作業時の時点では react-native upgrade が 0.59.0 以降に対応していなそうな挙動だった為 ※1
    • react-native upgrade で行われる事は、パッチ当てだという事が把握できた為
  • 上記の理由で、rn-diff-purge でテンプレートの差分を確認し、必要な差分を手動で取り込んで、最新版の 0.59.2 まで上げる事にした

  • (雑感)

    • react-native upgrade でパッチを当てても、rn-diff-purgeで差分を確認して手動で取り込んでも、バージョンを大きく上げる場合(=差分が多い場合)は、作業効率はあまり変わらなそう (どちらでやっても大変)
    • 細かくバージョンを上げていく場合(=差分が少ない場合)は、後者(=rn-diff-purge)のほうが効率がよさそう
// ※1

1. package.json の react-native のバージョンを 0.56.0 -> 0.59.1, react と react-test-renderer を 16.4.1 -> 16.8.5 に 変更

2. `$ yarn install

3. `react-native upgrade 0.59.1` //0.59.0 でも同様だった
    - `warn Specified version "0.59.1" is already installed in node_modules and it satisfies "0.59.1" semver range. No need to upgrade`

// 本来はココでローカルのファイルに diff が発生するはずだが、
// `No need to upgrade` となってしまう為、
// 作業時の時点では `react-native upgrade` が 0.59.0 以降に対応していなそう、と推測した

appendix

(今回の作業スコープから外した事)

  • 将来的に廃止されます、系の Warning
    • Warning: ListView is deprecated and will be removed in a future release. See https://fb.me/nolistview for more information

    • Warning: Async Storage has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/async-storage' instead of 'react-native'. See https://github.com/react-native-community/react-native-async-storage

    • Warning: WebView has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from 'react-native-webview' instead of 'react-native'. See https://github.com/react-native-community/react-native-webview

作業ログ

// node のバージョンが古いと native-base バージョンアップの際の `react-native link` 時に `rnpm-install info Assets have been successfully linked to your project` でハングアップする為、バージョンを上げておく
$ node -v
v10.14.0

// 作業開始前
$ react-native --version
react-native-cli: 2.0.1
react-native: 0.56.0

package.jsonreact-native のバージョンを 0.59.2 に上げて yarn install

// react-native の最新バージョンを確認 
$ npm info react-native version
0.59.2

// `package.json` の `react-native` のバージョンを `0.59.2` に書き換える 
$ git diff package.json
-    "react-native": "0.56.0",
+    "react-native": "0.59.2",

// react-native をバージョンアップ
$ yarn install

〜 略 〜
warning " > react-native@0.59.2" has incorrect peer dependency "react@16.8.3".
〜 略 〜

package.jsonreact のバージョンを上記の peer dependency のバージョン(=16.8.3) に上げて yarn install

// react を上記の peer dependency のバージョンにバージョンアップ

$ git diff package.json

-    "react": "16.4.1",
+    "react": "16.8.3",

-    "react-test-renderer": "16.4.1",
+    "react-test-renderer": "16.8.3",

$ yarn install

react-native 0.56.0 <-> 0.59.2 間のテンプレート差分を確認し、必要な差分を手動で取り込む

  • 備考
    • ios/以下の Info.plist 等のアプリの設定は、現設定をテンプレート差分で上書きしないように注意
      • 例えば、CFBundleIdentifier(=アプリ名) 等をテンプレート差分で上書きしてはいけない
    • Info.plist 等はファイルを直接編集せず、XCode 上から GUI で設定するのが望ましいのだと思うが、今回は差分を見ても XCode 上でどのような操作を行うべきか把握できなかった為、差分を確認してファイルを調節変更した
// 上記作業で package.json の変更があったので、変更内容を反映
$ yarn install

0.56.0 -> 0.57.0 へアップグレードする際に Manual Upgrades が必要らしいので、 3. の作業に加えて必要な差分があれば取り込む

  • 必要な差分はなかった

ビルド (iOS)

  • BUILD FAILED は発生しなかった

アプリ起動まで (iOS)

  • error: bundling failed: Error: Unable to resolve module `./build/boot/index` from `PATH/TO/MY_APP/App.js: The module `./build/boot/index could not be found from PATH/TO/MY_APP/App.js. Indeed, none of these files exist:

    • 解決方法
      • ターミナル と シミュレータ を再起動すると解消した
  • error: bundling failed: Error: Unable to resolve module `react-timer-mixin from `PATH/TO/MY_APP/node_modules/native-base/dist/src/basic/Tabs/index.js: Module react-timer-mixin` does not exist in the Haste module map

    • 解決方法
      • native-base をバージョンアップ
// native-base バージョンアップ

$ npm info native-base version
2.12.1

$ git diff package.json

-    "native-base": "2.8.1",
+    "native-base": "2.12.1",

$ yarn install
$ react-native link

$ rm -rf node_modules/
$ yarn install
 
// この後、ターミナル と シミュレータ を再起すると解消
  • error: bundling failed: Error: Unable to resolve module `react-native/Libraries/Components/View/ViewStylePropTypes` from `PATH/TO/MY_APP/node_modules/react-native-render-html/src/HTMLUtils.js`: Module `react-native/Libraries/Components/View/ViewStylePropTypes` does not exist in the Haste module map
// react-native-render-html バージョンアップ

$ npm info react-native-render-html version
4.1.2

$ git diff package.json
-    "react-native-render-html": "^3.10.0",
+    "react-native-render-html": "^4.1.2",
  • Application RnDiffApp has not been registered.
    • 解決策
      • 作業ミスで ios/MY_APP/AppDelegate.mmoduleNameRnDiffApp になってしまっていたので、本来のアプリ名に修正

アプリ起動後のワーニング対応 (iOS)

  • Require cycle: node_modules/react-native-safe-area-view/index.js -> node_modules/react-native-safe-area-view/withSafeArea.js -> node_modules/react-native-safe-area-view/index.js
// react-native-safe-area-view のバージョンを 0.9.0 以上に上げる
$ yarn upgrade react-native-safe-area-view
// react-navigatin の依存パッケージの react-native-safe-area-view のバージョンを 0.9.0 以上に上げる
$ yarn upgrade react-navigation
  • Provider: It is not recommended to assign props directly to state because updates to props won't be reflected in state. In most cases, it is better to use props directly.
$ npm info mobx-react version
5.4.3

$ git diff package.json
-    "mobx-react": "^5.2.3",
+    "mobx-react": "^5.4.3",

$ yarn install
  • Animated: `useNativeDriver` is not supported because the native animated module is missing. Falling back to JS-based animation. To resolve this, add `RCTAnimation` module to this app, or remove `useNativeDriver`.
    • 解決方法
      • 概要 3. の作業時に Link Binary With Libraries から libRCTAnimation.a を削除してしまっていたので、 XCode > TARGETS > MY_APP > Build Phases > Link Binary With Libraries から libRCTAnimation.a を追加

ビルド (Android)

  • ./gradlew: line 159: syntax error near unexpected token

    • 解決方法
      • 概要 3. の作業ミスで混入した android/gradlew の syntax error を修正
  • PATH/TO/MY_APP/android/app/src/main/AndroidManifest.xml Error: uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in 〜略〜 the library might be using APIs not available in 16

    • 解決方法
      • android/build.gradleminSdkVersion の指定が 16 になっていたので、19 に変更
  • WARNING: The specified Android SDK Build Tools version (27.0.3) is ignored, as it is below the minimum supported version (28.0.3) for Android Gradle Plugin 3.3.1.

    • 解決策
      • compileSdkVersion が 28 以下になっている箇所を 28 に変更
      • buildToolsVersion が 27.0.3 になっている箇所を 28.0.3 に変更
  • More than one file was found with OS independent path 'lib/x86/libc++_shared.so'

// android/app/build.gradle に packagingOptions を追加

android {
    packagingOptions {
      pickFirst 'lib/x86/libc++_shared.so'
      pickFirst 'lib/arm64-v8a/libc++_shared.so'
      pickFirst 'lib/x86_64/libc++_shared.so'
      pickFirst 'lib/armeabi-v7a/libc++_shared.so'
    }

実機テスト中のエラー (Android)

  • E/unknown:ReactNative: Exception in native call com.facebook.react.bridge.NoSuchKeyException: backgroundColor
    • 特定の端末でのみ発生
    • 発生要因
      • native-base 2.12.1 の不具合? で <Header><Left|Right> 内に、<Button transparent disabled={true}> があると、Android実機で NoSuchKeyException: backgroundColor が発生
    • 解決方法
      • <Button><TouchableOpacity> で代替し、問題を回避した