メインコンテンツへスキップ

Gitによるアップグレードの簡素化

·5分で読めます
Nicolas Cuillery
ZenikaのJavaScriptコンサルタント兼トレーナー

React Nativeの新しいバージョンへのアップグレードは困難でした。以前、このような画面を見たことがあるかもしれません。

これらの選択肢はどれも理想的ではありません。ファイルを上書きするとローカルの変更が失われます。上書きしないと最新のアップデートが適用されません。

本日、この問題を解決する新しいツールを紹介できることを誇りに思います。このツールは react-native-git-upgrade と呼ばれ、裏側でGitを使用して、可能な限り自動的にコンフリクトを解決します。

使い方

要件:Gitが PATH で利用可能である必要があります。プロジェクトがGitで管理されている必要はありません。

react-native-git-upgrade をグローバルにインストールします。

$ npm install -g react-native-git-upgrade

または、Yarn を使用する場合

$ yarn global add react-native-git-upgrade

その後、プロジェクトディレクトリ内で実行します。

$ cd MyProject
$ react-native-git-upgrade 0.38.0

注意: react-native の新しいバージョンをインストールするために「npm install」を実行しないでください。ツールが正しく機能するためには、古いプロジェクトテンプレートと新しいプロジェクトテンプレートを比較できる必要があります。上記の通り、まだ古いバージョンのままで、アプリフォルダ内で実行するだけです。

出力例

引数なしで react-native-git-upgrade を実行して、React Nativeの最新バージョンにアップグレードすることもできます。

AndroidとiOSのビルドファイルにおける変更を保持しようと試みるため、アップグレード後に react-native link を実行する必要はありません。

実装は、可能な限り介入が少なくなるように設計されています。一時ディレクトリにオンザフライで作成されるローカルGitリポジトリに完全に依存しています。プロジェクトのリポジトリ(使用しているVCSがGit、SVN、Mercurial、...または何も使用していないかにかかわらず)とは干渉しません。予期せぬエラーが発生した場合は、ソースが復元されます。

仕組み

重要なステップはGitパッチの生成です。このパッチには、アプリが使用しているバージョンと新しいバージョンの間でReact Nativeテンプレートに加えられたすべての変更が含まれています。

このパッチを取得するには、node_modules ディレクトリ内の react-native パッケージに埋め込まれているテンプレート(react-native init コマンドが使用するのと同じテンプレートです)からアプリを生成する必要があります。そして、現在のバージョンと新しいバージョンの両方でテンプレートからネイティブアプリが生成された後、Gitはプロジェクトに適応したパッチ(つまり、アプリ名を含むパッチ)を生成することができます。

[...]

diff --git a/ios/MyAwesomeApp/Info.plist b/ios/MyAwesomeApp/Info.plist
index e98ebb0..2fb6a11 100644
--- a/ios/MyAwesomeApp/Info.plist
+++ b/ios/MyAwesomeApp/Info.plist
@@ -45,7 +45,7 @@
<dict>
<key>localhost</key>
<dict>
- <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
+ <key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
[...]

あとは、このパッチをソースファイルに適用するだけです。以前の react-native upgrade プロセスではわずかな違いでもプロンプトが表示されていましたが、Gitは3-wayマージアルゴリズムを使用して変更のほとんどを自動的にマージし、最終的に使い慣れた競合区切り文字を残します。

    13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
<<<<<<< ours
CODE_SIGN_IDENTITY = "iPhone Developer";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/HockeySDK.embeddedframework",
"$(PROJECT_DIR)/HockeySDK-iOS/HockeySDK.embeddedframework",
);
=======
CURRENT_PROJECT_VERSION = 1;
>>>>>>> theirs
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../node_modules/react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-code-push/ios/CodePush/**",
);

これらのコンフリクトは通常、理解しやすいものです。区切り文字 ours は「あなたのチーム」を表し、theirs は「React Nativeチーム」と見なすことができます。

なぜ新しいグローバルパッケージを導入するのか?

React NativeにはグローバルCLI(react-native-cli パッケージ)が付属しており、node_modules/react-native/local-cli ディレクトリに組み込まれているローカルCLIにコマンドを委譲します。

上記で述べたように、プロセスは現在のReact Nativeバージョンから開始する必要があります。もし実装をlocal-cliに組み込んでいたら、古いバージョンのReact Nativeを使用している場合、この機能を利用することはできなかったでしょう。例えば、この新しいアップグレードコードが0.38.0でしかリリースされていなかった場合、0.29.2から0.38.0にアップグレードすることはできなかったでしょう。

Gitに基づくアップグレードは開発者エクスペリエンスの大きな改善であり、誰もが利用できるようにすることが重要です。グローバルにインストールされる別のパッケージ react-native-git-upgrade を使用することで、プロジェクトがどのバージョンのReact Nativeを使用しているかにかかわらず、この新しいコードを今日から使用できます。

もう一つの理由は、最近のMartin KonicekによるYeomanの廃止です。パッチを作成するために古いテンプレートを評価できるよう、これらのYeomanの依存関係をreact-nativeパッケージに戻したくありませんでした。

試してフィードバックを提供してください

結論として、この機能を楽しんで、自由に改善を提案したり、問題を報告したり、特にプルリクエストを送信したりしてください。各環境は少しずつ異なり、各React Nativeプロジェクトも異なります。この機能をすべての人にとってうまく機能させるためには、皆さんのフィードバックが必要です。

ありがとうございます!

このすべてが可能になったのは、素晴らしい企業であるZenikaM6 Web(アーカイブ)のおかげです!心から感謝申し上げます!