業務でReact Nativeのバージョンを0.38.0から0.42.3にアップグレードしましたが、このバージョン間は色々と変更も多く作業苦労しました。その際に実施したことや注意点、気づいたこと等をまとめておきます。
主に実施した手順
1. react-native-git-upgrade 実行
react-native-git-upgrade 0.42.3
2. conflictを修正
ios/
フォルダ以下のconflictがあまりに多く手動で解消できなかったため、iosフォルダはおいておき、それ以外の部分のconflictを解消。
3. ios/
フォルダを削除し新たにblankプロジェクトよりコピー
react-native init で 0.42.3
のBlank Projectを作成した後、iosフォルダをコピー。
4. XCodeでプロジェクト設定
XCodeでプロジェクトを開き、元のバージョン(0.38.0)も開いた状態で比較しながら手動でプロジェクト設定を修正。
5. NativeModuleを利用しているライブラリを更新
unlinkした後バージョンを更新しlink。
rnpm unlink react-native-xxxxxxxxx
# package.jsonのバージョンを更新
npm install
rnpm link react-native-xxxxxxxxx
6. iOS、Androidそれぞれでビルド
エラーが出たら随時修正していく
7 flowのエラーを修正
コード修正、もしくは.flowconfigのignoreの追加
気づいた点
空のプロジェクトでそれぞれのバージョンを比較するとわかりやすい
事前にそれぞれのバージョンでBlankのプロジェクトをreact-native init
で作って比較すると、バージョンが上がって実際にどこが変わるのかがわかりやすい。
react-native initでのバージョン指定は以下のように行う。
react-native init ReactNativeGraphSample --version <指定バージョン>
ちなみに以下は0.38.0と0.42.3 でそれぞれ作った際の差分
https://github.com/gaishimo/react-native-blank-app/compare/0.38.0...0.42.3#diff-4893035e3eb377ae826f0419b59dda90R345
上の差分を見てみると、かなり変更点が多く、*-tvOS/
等のフォルダが新たに出来ていてApple TV用の設定ファイル等が追加されているのがなんとなくわかる。ios/blankapp.xcodeproj/project.pbxproj
はかなり変更が多いのもわかる。。
ios設定のコンフリクト
react-native-git-upgrade
を実行した後、project.pbxproj
に発生した大量のコンフリクトをエディタで直接編集して解消しようと試みたが死亡した。プロジェクトが壊れてXCodeで開けなくなったりした。開けるようになってもその後linkしたりするとおかしくなったり..
あまりにも差分が多くて直接変更するのは厳しかったので、今回はブランクのプロジェクト(今回上げるバージョンの)からiosディレクトリを持ってきて必要なファイルをコピーした。その後XCodeの画面でアップグレード前のバージョン設定と比較しながら元々あった設定を適用していった。その後、元々あった設定ファイルで適用が必要そうなものは手動でmergeした。
project.pbxprojは差分があまりにも多い場合は直接編集するのはなかなか厳しいという実感。差分が少ない時、あるいはある程度プロジェクトファイルの構造を把握できていれば直接編集するのもありかも。
※ Androidの設定(android/
以下)についてはConflictがそこまでなかったため手動でmerge出来た
react-native-git-upgradeをする前にNativeModuleをUnlinkしておくとよいのでは(完了後再度リンクする)
react-native-git-upgrade
でアップグレードを行った場合、iosディレクトリで大量にconflictが発生するが、事前にNativeModuleをunlinkしておいてプロジェクトの設定をシンプルな状態にしておくと差分が少なくなりそう。
※ただし後で再度linkする必要がある
作業時に遭遇したエラー等のメモ
アップグレード後iOSビルドでエラー
...
Installing build/Build/Products/Debug-iphonesimulator/APPNAME.app
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
Failed to install the requested application
The bundle identifier of the application could not be determined.
Ensure that the application's Info.plist contains a value for CFBundleIdentifier.
Print: Entry, ":CFBundleIdentifier", Does Not Exist
Command failed: /usr/libexec/PlistBuddy -c Print:CFBundleIdentifier build/Build/Products/Debug-iphonesimulator/APPNAME.app/Info.plist
Print: Entry, ":CFBundleIdentifier", Does Not Exist
Info.plist では CFBundleIdentifierが以下のように定義されているが、
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
PRODUCT_BUNDLE_IDENTIFIER
が設定されていないためエラーになっていた。
PRODUCT_BUNDLE_IDENTIFIER
はXCodeのプロジェクト設定の[General]で指定できる。
NativeModuleのunlink時エラー
NativeModuleをunlinkする際に以下のエラーが出た。
$ rnpm unlink react-native-vector-icons
rnpm-link info Unlinking react-native-vector-icons android dependency
rnpm-link info Android module react-native-vector-icons has been successfully unlinked
rnpm-link info Unlinking react-native-vector-icons ios dependency
/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/xcode/lib/pbxProject.js:1147
var matches = searchPaths.filter(function(p) {
^
TypeError: searchPaths.filter is not a function
at pbxProject.removeFromLibrarySearchPaths (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/xcode/lib/pbxProject.js:1147:39)
at removeFromStaticLibraries (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/rnpm-plugin-link/src/ios/removeFromStaticLibraries.js:17:11)
at getProducts.forEach.product (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/rnpm-plugin-link/src/ios/unregisterNativeModule.js:36:5)
at Array.forEach (native)
at unregisterNativeModule (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/rnpm-plugin-link/src/ios/unregisterNativeModule.js:35:34)
at unlinkDependencyIOS (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/rnpm-plugin-link/src/unlink.js:52:3)
at Object.unlink [as func] (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/rnpm-plugin-link/src/unlink.js:94:3)
at Command.runAction (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/bin/cli:23:15)
at Command.listener (/Users/gaishimo/.nodebrew/node/v6.10.1/lib/node_modules/rnpm/node_modules/commander/index.js:301:8)
at emitTwo (events.js:106:13)
これに従ってツール(rnpm)のコードを直接いじって回避
https://github.com/facebook/react-native/issues/13160
雑感
バージョン間の変更が少なければスムーズに行く気がするが、変更が多いとかなり大変。根性が試される。日頃こまめにバージョンアップを行って、一度の作業のバージョン間があまり開かないようにできれば理想かも。