メインコンテンツまでスキップ

Expo SDK 47アップグレード

参考

以下の記事を参考にして、このアプリのExpo SDKを47にアップグレードしました。 主な変更点とこのアプリで実施したアップグレード手順を紹介します。

なお、このアプリでは使用していないため、EASやClassic Buildに関する内容は記載しません。

Expo SDK 47の主な変更

React Native 0.70.8 and React 18.1.0

より多くのReact NativeアプリでNew Architectureをサポートしやすくなりました。New Architectureに関する新しいドキュメントも公開されています。

また、このバージョンに含まれるHermesではInternationalization APIsもサポートされています。

詳細は、以下のリンク先を参照してください。

Fabricの実験的サポート

Expo SDK 47でFabricをサポートしている画面ライブラリは以下の3つです。

まだサポートされていない画面ライブラリは以下になります。

上記以外のExpoライブラリは全てNew Architectureと互換性があることを期待できます。

ただし、Managed workflowのアプリにはFabricを有効にする機能がまだありません(Config Pluginsを使用して有効化できますが、推奨されていません)。

Expo Go for iOSのHermesサポート

HermesがExpo Go for iOSで利用できるようになりました。

また、Hermes inspectorをExpo Goや開発ビルドの開発メニューから直接開けるようになりました。これは、Flipperで利用できるデバッガーと同じもので、Flipper SDKやFlipper desktop app使用時のオーバーヘッドなしで利用できます。

なお、Expo SDK 48ではHermesがデフォルトで有効になります。

Config Plugins

expoパッケージから、@expo/config-plugins@expo/configを再エクスポートするようになりました。

expoパッケージからインポートすることにより、使用しているExpo SDKのバージョンに依存したConfig Pluginsを使用できます。 そのため、Expo SDK 47からは@なしのexpo/config-pluginsexpo/configを使用することが推奨されます。

// Expo SDK 46
import {ConfigPlugin, withPlugins} from '@expo/config-plugins';
import {Platform} from '@expo/config';

// Expo SDK 47
import {ConfigPlugin, withPlugins} from 'expo/config-plugins';
import {Platform} from 'expo/config';

Expoがサポートするライブラリや機能

ライブラリの更新

Expoが管理しているライブラリの内、メジャーバージョンアップなど大きなリリースがあったものを記載します。

非推奨となるライブラリ

以下のライブラリが非推奨となりました。

Classic Buildsのサポート終了

Classic Buildsのサポートは終了しました。EAS Buildへの移行はMigrating from "expo build"を参照してください。

app.jsonの非推奨となっていた項目の削除

以下の項目がapp.jsonから削除されました。

  • useNextNotificationsApi
  • android.googleSignIn
  • ios.merchantId
  • ios.googleSignIn
  • ios.splash.xib

iOSの最小サポート対象バージョンが13.0に変更

iOSのサポート対象バージョンが13.0以降になりました。

アクティブなデバイスにおける現在のiOSのバージョン分布は、Appleが公開しているApp Storeのデータで確認できます。

Expo SDK 44のサポート終了

Expo SDK 44がサポート対象外になりました。Expo SDK 44を使用している場合は、Expo SDK 45以降にアップグレードする必要があります。

このアプリで実施したアップグレードの手順

このアプリでは、以下の作業を上から順に実施してExpo SDK 47にアップグレードしました。

アップグレードを実施したPull Requestはこちらです。

開発・CIに使用しているツールのバージョンを更新

Expo SDK 47のアップグレードとは関係ありませんが、このタイミングで開発に使用しているツールのバージョンを更新しました。

Toolfromto
Node.js16.18.018.15.0
Javazulu-11.58.23zulu-11.62.17

Node.jsの18系へのアップグレードに伴い、npmのバージョンも9系にアップグレードしています。npmの9系では、lockfileVersion3が使用されます。

また、CIに使用しているツールのバージョンも更新しました。

Toolfromto
Node.js16.18.018.15.0
Xcode14.0.114.2

既存のパッチファイルの更新

このアプリでは、patch-packageを使用して、以下のライブラリにパッチファイルを適用していました。パッチ内容の詳細は、こちらを参照してください。

  • @expo/config-plugins
  • @react-native-community/cli-platform-ios
  • expo-splash-screen
  • react-native-reanimated
  • react-native-elements

react-native-reanimatedに適用していたパッチは、以下のPRで修正されたためパッチフィルを削除しました。

@react-native-community/cli-platform-iosexpo-splash-screenは、Expo SDKのアップグレードに伴いバージョンが上がりました。しかし、適用していたパッチファイルはまだ必要な対応だったため、パッチファイルは削除せずに各ライブラリのバージョンに合わせてファイル名をリネームしました。

上記以外のライブラリに関しては、バージョンが変わらなかったため変更はありません。

expo-cli upgradeで更新されるパッケージに依存するパッケージの更新

Expo SDKのアップグレードに伴い、jest-expoのバージョンが上がりました。アップグレードされたjest-exporeact-test-renderer18.1.xに依存しています。

そのため、このアプリでも依存ライブラリとして追加している@testing-library/react-nativeのバージョンを18.1.0にアップグレードしました。

Config Pluginsのimportをexpo/config-pluginに変更

Expo SDK 47の主な変更 - Config Pluginsに記載した通り、expoパッケージから、@expo/config-plugins@expo/configを再エクスポートするようになりました。

それに伴い、このアプリでインポートしている@expo/config-pluginsexpo/config-pluginsに変更しました。なお、このアプリでは、@expo/configを使用していません。

// 変更前
import {ConfigPlugin, withPlugins} from '@expo/config-plugins';

// 変更後
import {ConfigPlugin, withPlugins} from 'expo/config-plugins';

expo-template-blank-typescriptの更新履歴を確認

expo-template-blank-typescriptの更新履歴を確認しました。

expo-cli upgradeで更新される依存ライブラリのアップグレードが主な変更だっため、このアプリで特別な対応は必要ありませんでした。

expo-template-bare-minimumの更新履歴を確認

expo-template-bare-minimumの更新履歴を確認しました。

このアプリではConfig Pluginsに対応したので、expo-template-bare-minimumの更新に伴う個別の対応は基本的に必要ありません。 ただし、このアプリで作成しているConfig Pluginsによる変更と、expo-template-bare-minimumの更新に伴う変更が競合した場合は、個別に対応する必要があります。

そのため、上記内容を観点にexpo-template-bare-minimumを確認しましたが、個別に対応する必要はありませんでした。

TSCのエラー対応

@react-native-datetimepicker/datetimepickerの以下のPRで型定義が変更されました。

iOSの場合は、dateが削除されています。

その影響で、このアプリのDateTimePicker.ios.test.tsxでTSCエラーが発生しました。

src/bases/ui/picker/DateTimePicker.ios.test.tsx:155:29
- error TS2339: Property 'date' does not exist on type 'Readonly<Readonly<ViewProps & BaseOptions & { maximumDate?: Date | undefined; minimumDate?: Date | undefined; }> & { locale?: string | undefined; ... 7 more ...; disabled?: boolean | undefined; }>'.
155 expect(pickerItemsProps.date).toBe(selectedValue.getTime());

@react-native-datetimepicker/datetimepickerでは、選択された値を取得するためにonChangeを利用します。 そのため、直接dateを参照する必要はないのですが、このアプリでは自動テスト時にdateを参照して選択した値を検証していました。

dateは外部に非公開となりましたが、@react-native-datetimepicker/datetimepickerの内部では、dateをネイティブモジュールに渡しています。 自動テスト時の検証としては有効だと考え、以下のように@ts-ignoreを追加してTSCエラーを回避しました。

// ↓の対応で型定義からdateは削除されましたが、react-native-datetimepickerの内部ではdateを使用しているようなので、selectedValueとdateを比較します
// https://github.com/react-native-datetimepicker/datetimepicker/pull/671
// https://github.com/react-native-datetimepicker/datetimepicker/blob/v6.5.2/src/datetimepicker.ios.js#L97
// @ts-ignore
expect(pickerItemsProps.date).toBe(selectedValue.getTime());

手動管理しているライセンスの更新

このアプリでは、使用しているライブラリのライセンス一覧を出力するスクリプトを用意しています。詳細は、こちらを参照してください。

その中で、ライセンス情報が不足しており補完したい、あるいは、開発時のみ使用するため除外したいライブラリとバージョンをmanaged-license.jsで管理しています。

今回のExpo SDKアップグレードでは、managed-license.jsで管理しているMetroのパッケージが更新されたため、アップグレード後のバージョンに併せてライセンス情報を更新しました。