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

Gitによる簡単なアップグレード

·4分間の読書
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方向マージアルゴリズムを使用してほとんどの変更を自動的にマージし、最終的には使い慣れた競合区切り文字を残すことができます

    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のバージョンに関係なく、今日この新しいコードを使用できます。

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

試してフィードバックを提供する

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

ありがとうございます!

素晴らしい企業であるZenikaM6 Web(アーカイブ)に感謝いたします。彼らがいなければ、これは不可能でした!