この記事の内容
- 仕事で使っているアプリを0.55.2 -> 0.56.0にアップグレードしたので、その際試した方法、ハマった内容などを共有
- マイグレーションは大変と噂ですが、割と大変
はじめに
- 公式ガイド: https://facebook.github.io/react-native/docs/upgrading.html
- リリース内容: https://github.com/facebook/react-native/releases
- 方法としては
- 公式の
react-native-git-upgrade
を使ってバージョン間の変更を適用する - 指定バージョン間のdiffを見るツール https://github.com/ncuillery/rn-diff/compare/rn-0.55.2...rn-0.56.0 で変更をみつつ自力でマイグレーションする
-
package.json
書き換えるなりreact-native init
して差分見るなりしてがんばる
- 公式の
- などがあります。今回は1をやろうとして3に切り替えましたが、2を見つつ3が一番楽そう
- 今回の対象プロジェクト は lerna のmonorepoで、multi packege構造だった
- やること
- packege.json の
react
,react-native
のバージョンアップ - interfaceの変更に伴い
build.gradle
やxxx.xcodeproj
や.flowconfig
なども必要なら書き換える - それにより他のライブラリやJSコード、ネイティブコードが動かなくなるので、一つ一つエラーを見て直していく
- 後は気合
- packege.json の
0.56の変更点
- https://github.com/facebook/react-native/releases から大きいところ
- 2018/4/4の0.55から816コミット分の変更
- Babel 7対応
- Android 26 SDK対応
- Node 8 がminimum required versionに
- iOS9 が minimum required versionに
- Xcode 9 が minimum required versionに
- 他にも100くらいの変更あるので公式を参照
プロジェクトのディレクトリ構造
色々省略してますが
$ tree -L 2 -I node_modules
.
├── lerna.json
├── package.json
├── packages
│ ├── network
│ ├── domain
│ ├── i18n
│ └── main
├── tsconfig.json
├── tslint.json
├── vendor
│ └── bundle
└── yarn.lock
-
packages/main
がメインのアプリケーションのソースコードで、react-nativeに依存しているのはそこだけ -
packages/main
内にあるpackege.json 内のdependencies
にnetwork
やdomain
等のパッケージへの依存が書かれてます
プロジェクトの事情
- ReactNative触るのは全員モバイルエンジニア(Mac)
- React Nativeを一からTypeScriptで開発しているプロジェクトで、git cloneしてきたらとりあえず
init.sh
叩く、みたいにしてる -
init.sh
が行なっているのはnpm install
->bundle install
->pod install
->tsc build
の一連の環境設定の流れ(ほんとはデベロップメントサーバー起動とか色々ある)
react-native-git-upgrade試した
$ yarn global add react-native-git-upgrade
$ cd packages/main
$ react-native-git-upgrade
エラー xxxx(パッケージ名): Not found
lernaの独自パッケージが参照できずにエラー発生
error An unexpected error occurred: "https://registry.yarnpkg.com/xxxx: Not found".
git-upgrade ERR! An error occurred during upgrade:
git-upgrade ERR! Error: Command 'yarn add react-native@0.56.0 react@16.4.1' exited with code 1:
stderr: undefined+ cd ../xxxx
-
react-native-git-upgrade
を実行するとreact
とreact-native
パッケージをアップグレードして、同時に公式レポジトリに入っている変更を適用しようとする - lernaには対応してないので
npm update
に失敗するので、mainパッケージのエラーになったdependenciesを消してみる
再度react-native-git-upgrade実行
普通にいくと下記みたいな出力が出る
git-upgrade info Check for updates
git-upgrade info Using yarn 1.7.0
git-upgrade info Read package.json files
git-upgrade info Check declared version
git-upgrade info Check matching versions
git-upgrade info Check React peer dependency
git-upgrade info Check that Git is installed
git-upgrade info Get information from NPM registry
git-upgrade info Upgrading to React Native 0.56.0, React 16.4.1
git-upgrade info Setup temporary working directory
git-upgrade info Configure Git environment
git-upgrade info Init Git repository
git-upgrade info Add all files to commit
- conflictが発生
z1Vi_Zy=U>ksq-G_fM)m29;BR$>lFp~S*{+8W;-V<x(&S9j{qRW5YUQ=V&qVCbh(gE
z1LtGy9zHsxDTSaBmKCgK2%rMY$WK9|m-LzMgv@jUVUKukgw!~V#?v<}@9dn>zpOg_
z{-6B_%gK~tgzphw9K=
at ChildProcess.child.on.code (/Users/username/.config/yarn/global/node_modules/react-native-git-upgrade/cliEntry.js:58:18)
at emitTwo (events.js:126:13)
at ChildProcess.emit (events.js:214:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)
git-upgrade ERR! Restore initial sources
error: Your local changes to the following files would be overwritten by checkout:
node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj/xcuserdata/username.xcuserdatad/xcschemes/xcschememanagement.plist
node_modules/react-native/React/React.xcodeproj/xcuserdata/username.xcuserdatad/xcschemes/xcschememanagement.plist
Please commit your changes or stash them before you switch branches.
Aborting
Error: Command 'git checkout project-snapshot' exited with code 1:
stderr: undefinederror: Your local changes to the following files would be overwritten by checkout:
node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj/xcuserdata/username.xcuserdatad/xcschemes/xcschememanagement.plist
node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj/xcuserdata/username.xcuserdatad/xcschemes/xcschememanagement.plist
node_modules/react-native/React/React.xcodeproj/xcuserdata/username.xcuserdatad/xcschemes/xcschememanagement.plist
Please commit your changes or stash them before you switch branches.
Aborting
stdout:
at ChildProcess.child.on.code (/Users/username/.config/yarn/global/node_modules/react-native-git-upgrade/cliEntry.js:58:18)
at emitTwo (events.js:126:13)
at ChildProcess.emit (events.js:214:7)
at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)
- 全部の出力だとすごい長いので省略してます
- この出力見てもよく分からないけど、react-nativeの本家の変更がgitのchangesに出てくる
- コマンドの実行結果はdiffみたいな内容が出力されることもある
-
git status
の結果に最新のReact Nativeとの差分(https://github.com/ncuillery/rn-diff/compare/rn-0.55.2...rn-0.56.0 と大体一緒)が出ている
$ git status
On branch feature/rn_migration
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: .babelrc
modified: .flowconfig
modified: android/app/build.gradle
modified: android/app/proguard-rules.pro
modified: android/app/src/main/AndroidManifest.xml
modified: android/app/src/main/res/mipmap-hdpi/ic_launcher.png
modified: android/app/src/main/res/mipmap-mdpi/ic_launcher.png
modified: android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
modified: android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
modified: android/app/src/main/res/values/strings.xml
modified: android/app/src/main/res/values/styles.xml
modified: android/build.gradle
modified: android/gradle.properties
modified: android/gradle/wrapper/gradle-wrapper.properties
modified: android/settings.gradle
modified: app.json
modified: package.json
modified: yarn.lock
Untracked files:
(use "git add <file>..." to include in what will be committed)
.gitattributes
.gitignore
.watchmanconfig
android/app/BUCK
android/app/src/main/java/com/
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
android/app/src/main/res/mipmap-xxxhdpi/
android/keystores/
ios/main-tvOS/
ios/main-tvOSTests/
ios/main.xcodeproj/
ios/main/
ios/mainTests/
no changes added to commit (use "git add" and/or "git commit -a")
- 特に取り込むべき変更が見当たらなかったのでpackage.jsonだけ書き換える方針に切り替え(flow typeとか使ってたら
.flowconfig
など取り入れるべきと思います) - git の変更を全て破棄してから下記を変える
- "react": "16.3.1",
- "react-native": "0.55.2",
+ "react": "16.4.1",
+ "react-native": "0.56.0",
起動確認
- init.shで環境整備(npm install, tsc buildなど諸々)し、
react-native run-android
などで実機起動する - 当然途中で諸々のエラーが発生する
エラー CocoaPodsで"Folly"が見つからないエラー
-
pod install
の途中で下記のエラー
[!] CocoaPods could not find compatible versions for pod "Folly":
In snapshot (Podfile.lock):
Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
In Podfile:
Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
None of your spec sources contain a spec satisfying the dependencies: `Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`), Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)`.
You have either:
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
* mistyped the name or version.
* not added the source repo that hosts the Podspec to your Podfile.
Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
ios/Podfile.lock
と ios/Pods/
を消して再度 pod install
エラー Could not find com.facebook.react:react-native:0.xx.x.
-
react-native run-android
失敗した
FAILURE: Build failed with an exception.
* What went wrong:
Could not resolve all files for configuration ':app:debugCompileClasspath'.
> Could not find com.facebook.react:react-native:0.55.2.
Searched in the following locations:
file:/Users/username/Library/Android/sdk/extras/m2repository/com/facebook/react/react-native/0.55.2/react-native-0.55.2.pom
- build.gradle内で読み込むreact-nativeのバージョンが違う
- package.jsonのバージョンと合わせる
build.gradleの修正
-implementation "com.facebook.react:react-native:0.55.2"
-implementation "com.facebook.react:react-native:0.56.0"
エラー Cannot find module 'babel-preset-react-native-dotenv'
- 環境変数の定義に
react-native-dotenv
を使っているが、実機でテストするとエラーが発生
Loading dependency graph, done.
error: bundling failed: Error: Cannot find module 'babel-preset-react-native-dotenv' from '/Users/username/Desktop/workspace/packages/main'
- If you want to resolve "react-native-dotenv", use "module:react-native-dotenv"
at Function.module.exports [as sync] (/Users/username/Desktop/workspace/packages/main/node_modules/resolve/lib/sync.js:42:15)
babel-preset-react-native-dotenv
moduleが見つからない
https://github.com/zetachang/react-native-dotenv/issues/44
対応方法
- バージョン
0.2.0
を指定すればOK - 当時
react-native-dotenv
がv56に対応していなかったので暫定でforkされたrepositoryを参照するよう変更した - .babelrcを下記に変更
{
"presets": ["react-native", "module:react-native-dotenv"]
}
- package.json修正
- "react-native-dotenv": "^0.1.1",
+ "react-native-dotenv": "^0.2.0",
エラー babel-preset-react-native のバージョンが低い
Loading dependency graph, done.
error: bundling failed: TypeError: Cannot read property 'bindings' of null
at Scope.moveBindingTo (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/scope/index.js:978:13)
at BlockScoping.updateScopeInfo (/Users/username/Desktop/workspace/packages/main/node_modules/babel-plugin-transform-es2015-block-scoping/lib/index.js:364:17)
at BlockScoping.run (/Users/username/Desktop/workspace/packages/main/node_modules/babel-plugin-transform-es2015-block-scoping/lib/index.js:330:12)
at PluginPass.BlockStatementSwitchStatementProgram (/Users/username/Desktop/workspace/packages/main/node_modules/babel-plugin-transform-es2015-block-scoping/lib/index.js:70:24)
at newFn (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/visitors.js:237:21)
at NodePath._call (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/path/context.js:65:20)
at NodePath.call (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/path/context.js:40:17)
at NodePath.visit (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/path/context.js:100:12)
at TraversalContext.visitQueue (/Users/username/Desktop/workspace/packages/main/node_modules/@babel/traverse/lib/context.js:142:16)
- https://stackoverflow.com/questions/51178388/react-native-crashes-after-upgrade-to-version-0-56-possible-babel-issue
- package.jsonのbabel-preset-react-nativeのバージョンを変更
- リリースノートにも書いてある https://github.com/facebook/react-native/releases/tag/v0.56.0
- 古いプロジェクトだと
babel-bridge
を使った方が下位互換が保てる?今回は使いませんでした
"babel-preset-react-native": "^5".
エラー error: bundling failed: Error: Unable to resolve module react-native/Libraries/Renderer/shims/ReactNativePropRegistry
- 実機実行してJSのロード中に
NativeBase
のエラー
error: bundling failed: Error: Unable to resolve module `react-native/Libraries/Renderer/shims/ReactNativePropRegistry` from `/Users/username/Desktop/workspace/packages/main/node_modules/native-base/dist/src/Utils/computeProps.js`: Module `react-native/Libraries/Renderer/shims/ReactNativePropRegistry` does not exist in the Haste module map
This might be related to https://github.com/facebook/react-native/issues/4968
To resolve try the following:
1. Clear watchman watches: `watchman watch-del-all`.
2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
3. Reset Metro Bundler cache: `rm -rf /tmp/metro-bundler-cache-*` or `npm start -- --reset-cache`. 4. Remove haste cache: `rm -rf /tmp/haste-map-react-native-packager-*`.
at ModuleResolver.resolveDependency (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:167:1306)
at ResolutionRequest.resolveDependency (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:80:16)
at DependencyGraph.resolveDependency (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/node-haste/DependencyGraph.js:237:485)
at Object.resolve (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/lib/transformHelpers.js:116:25)
at dependencies.map.result (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/DeltaBundler/traverseDependencies.js:298:29)
at Array.map (<anonymous>)
at resolveDependencies (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/DeltaBundler/traverseDependencies.js:294:16)
at /Users/username/Desktop/workspace/packages/main/node_modules/metro/src/DeltaBundler/traverseDependencies.js:159:33
at Generator.next (<anonymous>)
at step (/Users/username/Desktop/workspace/packages/main/node_modules/metro/src/DeltaBundler/traverseDependencies.js:239:307)
-
node_modules/native-base/dist/src/Utils/computeProps.js
あたりで発生 - native-baseの最新バージョンで対応済み
- https://github.com/GeekyAnts/NativeBase/issues/2028
- "native-base": "^2.4.1",
+ "native-base": "^2.7.0",
エラー 型定義が変わった
- TypeScriptを使っている場合、型定義ファイルも更新しなければいけない
- TextInputのonFocusに引数が増えた
main: src/components/FormItem.tsx(98,76): error TS2554: Expected 1 arguments, but got 0.
main: src/components/FormItem.tsx(117,22): error TS2326: Types of property 'display' are incompatible.
main: Type 'boolean' is not assignable to type 'undefined'.
- 型定義に合わせてコードを修正
エラー jestが実行できない
- テスト対象ファイル全部ビルド失敗
Plugin 0 specified in "project/node_modules/babel-preset-react-native/index.js" provided an invalid property of "default" (While processing preset: "project/node_modules/babel-preset-react-native/index.js")
- 関連issue
- jest系のパッケージをまとめてアップデート
- "babel-core": "^6.26.0",
+ "babel-core": "^7.0.0-beta.54",
- "babel-jest": "22.4.3",
+ "babel-jest": "23.2.0",
- "jest": "22.4.3",
+ "jest": "23.2.0",
- "ts-jest": "^22.4.4",
+ "ts-jest": "^23.0.0",
"jest": {
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
}
}
エラー jest で setTimeoutが動かない?
TypeError: Cannot read property 'debug' of undefined
at /Users/username/Desktop/workspace/packages/main/dist/data/HogeLib.js:26:44
at Timeout._onTimeout (/Users/username/Desktop/workspace/packages/main/dist/data/__test__/HogeLib.test.js:27:13)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
Jest did not exit one second after the test run has completed.
- 上記からtestが動かない現象、もしくはこれも出ないで永遠にyarn testが終わらない現象が起きました
- テストコードから不要なsetTimeoutを除去したら起こらなくなりました
エラー Androidのlintが通らない
/Users/username/Desktop/workspace/packages/main/android/app/build/intermediates/res/merged/release/drawable-xhdpi/assets_img_ic_ic.png: error: uncompiled PNG file passed as argument. Must be compiled first into .flat file..
uncompiled PNG file passed as argument. Must be compiled first into .flat file
- 関連issue
- https://github.com/facebook/react-native/issues/16906
- https://github.com/react-navigation/react-navigation/issues/3097
- aapt通してcompileすると
.flat
ファイルを想定してるのでエラーになる? -
android/gradle.properties
にandroid.enableAapt2=false
を追加すると直る、が2018年末にこの設定は削除される予定らしいので暫定対応。うちのプロジェクトだとこれ以外の修正方法がうまくいかなかったけど、どこかのタイミングで修正したい
エラー AndroidのReleaseビルドが通らない
verifyReleaseResources/home/circleci/.gradle/caches/transforms-1/files-1.1/appcompat-v7-26.1.0.aar/0af13b712ba9e9b567dee09bc2b2f546/res/values-v26/values-v26.xml:13:5-16:13:AAPT: No resource found that matches the given name: attr 'android:keyboardNavigationCluster'
- 使っているネイティブライブラリがAndroid SDK 26に対応していない
- react-native-navigation など四つぐらいあって、各レポジトリにPRやissueが上がっていた
- うちのテックリードがライブラリプロジェクトのSDKバージョンを書き換えるgradle task書いてくれた。超感謝
+ext {
+ compileSdkVersion = 27
+ targetSdkVersion = 27
+}
+
+subprojects {
+ afterEvaluate { project ->
+ if (project.hasProperty("android")) {
+ android {
+ compileSdkVersion rootProject.ext.compileSdkVersion
+ }
+ }
+ }
+}
CircleCI落ちた
ipa作成時
[23:53:47]: ▸ ❌ ld: could not reparse object file in bitcode bundle: 'Invalid bitcode version (Producer: '902.0.39.2_0' Reader: '900.0.39.2_0')', using libLTO version 'LLVM version 9.0.0, (clang-900.0.39.2)' for architecture arm64
[23:53:47]: ▸ ❌ clang: error: linker command failed with exit code 1 (use -v to see invocation)
[23:53:47]: ▸ ** ARCHIVE FAILED **
- https://stackoverflow.com/questions/51128462/vsts-build-generation-not-working
- Bitcodeのバージョン違いでエラーが発生するケースがあるらしいので、Xcode(が中で使っているBitcode生成のLLVMバージョン?)のバージョンを上げたらうまく行った
ビルド後、JSロード時に失敗する
lerna ERR! Unable to resolve module `../utils/mapPropsToStyleNames` from `/Users/username/project/packages/main/node_modules/native-base/dist/src/basic/Text.js`: The module `../utils/mapPropsToStyleNames` could not be found from `/Users/username/project/packages/main/node_modules/native-base/dist/src/basic/Text.js`. Indeed, none of these files exist:
- キャッシュが原因だった
- よく分からないとこでmodule読み込めないよって言われる
- node_modules と TypeScriptビルドしたコードを削除したら動く
iOSがリロードでクラッシュ
- react-native-navigation のバージョンが古い
Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x1124771ce (Missing)
1 libobjc.A.dylib 0x1108ec031 objc_exception_throw
2 CoreFoundation 0x1124f8784 (Missing)
3 UIKit 0x10e97f6db (Missing)
4 CoreFoundation 0x1123f9898 (Missing)
5 CoreFoundation 0x1123f9278 (Missing)
6 app 0x10b247421 -[RCCViewController sendGlobalScreenEvent:endTimestampString:shouldReset:] (RCCViewController.m:225)
7 app 0x10b2480f9 -[RCCViewController viewDidDisappear:] (RCCViewController.m:293)
参考リンク
ここら辺読んでからやりました。感謝
https://qiita.com/ponnjinnka/items/b1fdd200b1bc094c6797
https://qiita.com/hotchpotch/items/5617caccd8749f410631