📚

Expo Bare workflowのアプリをManaged workflowに移行した話

2023/12/18に公開

こんにちは!@mrtryです。ventusでは、モバイルアプリの技術顧問として働いています。

この記事は、React Native Advent Calendar 18日目の記事になります🌲

https://qiita.com/advent-calendar/2023/react-native

数年前にExpoのBare workflowで作ったアプリを、Managed workflowに移行しました🥳
そのときの背景や、学びについてシェアできればと思います💃

Bare workflowでつくった背景

このモバイルアプリは、2020年に実装し始めました。まだEAS Buildがなかったタイミングだったので、「Managed workflowでは、Expo SDK以外のNative Moduleを採用できない」という成約がありました。このモバイルアプリには、アプリ内決済機能が必要だったのですが「Expo SDKから提供されているアプリ内決済機能は、Bare workflowでしか利用できない」という問題がありました。そういった背景で、実質Bare workflow一択となり、Bare workflowでアプリを作り始めたという背景がありました。

Managed workflowへのreplaceのモチベーション

そう意思決定はしたものの、数年Bare workflowで運用していくと以下のような面倒事がありました

  • Expo SDKだけでなくReact Native自体のupdateを頑張らないといけない
  • iOSの証明書やProvisioning Profileの管理が面倒
  • CI/CDをAndroid/iOSに合わせてLinuxとmacOSで構築必要

ですが、今ではEAS BuildのおかげでManaged workflowであってもExpo SDK以外のNative Moduleを利用できるようになりました。というわけで、上記の面倒事の解消のために、Bare workflowからManaged workflowへ移行することにしました。

行った移行作業

ドキュメントに記載されている内容以外で行ったworkaroundを色々紹介します

依存ライブラリのバージョンを整える

導入しているExpo SDKとインストールされているExpoまわりのライブラリのバージョンが合致していないものが色々ありました。解決するために、以下のcommandでExpo SDKと各ライブラリのバージョンを合わせました。

$ expo doctor --fix-dependencies

ある程度はこれで修正されますが、修正されなかったものについてはコマンドのログを見ながら手動で調整を行いました。

Dev Clientへの移行

Dev Clientへの移行は以下のようなことをしました

  • android/ iOS/ の内容を app.config.ts に移す
  • eas.jsonを書く
  • Intlが組み込まれているjscを使うようにpluginを書く

最初の2点は「ドキュメントを読んで、書き写しました」ぐらいなので省略し、Pluginについて紹介します。

弊社のアプリのJS実行環境は、Hermesに移行していなくJSCのままになっていました。また、JSCは org.webkit:android-js ではなく org.webkit:android-js-intl を利用していました。

今回の移行では、JSCのままManaged workflowへの移行をしようとしていたのですが、Managed workflowで利用されているJSCは org.webkit:android-js-intl ではなく org.webkit:android-js でした。

https://github.com/expo/expo/blob/sdk-46/android/app/build.gradle#L114

そのため、JSCをIntlのものを利用するためにExpo Pluginを書く必要があり、以下のようなコードで対応しました。

/*
 * Androidのbuild.gradleを変更するplugin
 * */
const {
  createRunOncePlugin,
  withAppBuildGradle
} = require('@expo/config-plugins')

const withAppBuildGradleModified = config => {
  return withAppBuildGradle(config, async file => {
    // Intlを利用するためにjscを変更する
    const modifiedContent = file.modResults.contents.replace(
      'org.webkit:android-jsc:+',
      'org.webkit:android-jsc-intl:+'
    )

    file.modResults.contents = modifiedContent
    return file
  })
}

module.exports = createRunOncePlugin(
  withAppBuildGradleModified,
  'withAppBuildGradleModified',
  '1.0.0'
)

証明書の移行

今まで利用していた証明証をEASにアップロードしました。基本的には以下のドキュメントに従ってアップロードするだけでした。

https://docs.expo.dev/app-signing/existing-credentials/

Androidは困らなかったのですが、iOSは少し手間取りました。Bare workflowのときのiOSの証明書管理にfastlane matchを利用していました。fastlane matchで作成していた証明書を、そのままEASにアップロードしようとしたのですが、なにか上手く行きませんでした(残念ながら、何がダメだったのかは結構前のため忘れてしまいました...)。workaroundとして、「iOSの証明書は再発行しても困らない」のと「Provisiong Profileは毎年どうせ作り直す」ということもあり、EASで証明書とProvisiong Profileを新規作成して対処しました。

Replaceして良かったこと

環境構築が簡素になった

Managed workflowに移行したことで、アプリの環境構築が簡素になりました。新しいチームメンバーに対してのオンボーディングが簡単になる利点もありますが、ウェブフロントやバックエンドのエンジニアがデバッグしやすくもなります。手を動かすエンジニアだけでなく、他のチームのエンジニアもアプリを動かしやすくすることで、クロスファンクショナルなチームに近づく一歩になるかなと思いました。

React Nativeのupdateから開放された

Managed workflowであればExpo SDKのバージョンアップだけで終わりますが、Bare workflowだとReact Nativeのバージョンアップも必要になります。React Nativeのバージョンアップをやったことがある人だとわかると思いますが、React Nativeのバージョンアップはたいへんです。

ある程度のupdate作業は $ npx react-native upgrade で対応できますが、Native Layerのコードに手を入れている場合はだいたいconflctが発生します。発生したNative Layerのconflictは、修正のためにAndroid/iOSの知識が必要になります。そのため、対応できるメンバーが限られたり、Android/iOSがわかる人でも「壊れた理由はわかるけど、地味にめんどくさい」という気持ちになりがちだと思います。

大多数のReact Native採用モチベーションは「管理コストを最小化し、プロダクト開発に注力できるようにしたい」からだと思います。その文脈を考えると、React Nativeのアップデート作業は「最小化したい管理コスト」に当たると思います。今回のreplaceでReact Nativeのupgrade作業がなくなったので、空いた時間はプロダクト開発に割いていきたいですね😎

CI/CDがシンプルになった

Bare workflowを利用していたとき、CI/CDの実行環境はAndroid用にLinux、iOS用にmacOSがありました。そのため、CI/CDにおいてもAndroid/iOSでworkflowの書き分けが必要になっていました。

今回のreplaceで、Android/iOSのBuildはEAS Buildに一元がされました🥳そのおかげで、CI/CD上で実行するタスクはJS Layerに関するものだけになり、JS Layerに関するcodegenやLintが終わった後は、EAS Buildにeas-cliからBuildのrequestを送るだけになりました。このおかげで、WorkflowのファイルがAndorid/iOSそれぞれありましたが、ひとつにまとまりました。

Android/iOSのモバイルのOSだけでなく、CI/CDを実行するWorkflowの実行環境も1環境だけになることで、保守運用のしやすさにもつながったと思います。

おわりに

Expo Bare workflowのアプリをManaged workflowに移行した話をしました。Managed workflowに寄せたことで、管理コストが大幅に削減することができました。特に、Native Layerのバージョンアップは疲弊することが多いので、そこの保守運用がなくなったことは大きいと感じました。今後も便利なものを取り入れていき、サービス開発に注力できる環境にしていきたいと思います!💃

React Nativeの最新技術を活かして、一緒にイノベーションを起こそう!ventusはスポーツ・エンタメ分野をリードする7年目のスタートアップです。BE FREAKIN' GEEK!

https://ventus-inc.com/recruit

Discussion