It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

【ReactNative】React Nativeで開発を始めるにあたって

最近趣味でReactNativeを触っていましたが、タイミングよく業務でもReactNativeのアプリに関わることになりました。 趣味の範囲では、適当に触って入ればよかったのですが、流石に業務で使うとなると少し真面目に勉強しなくてはいけないなと思い始めています。

ReactNativeはまだまだ日本語のドキュメントも少なく、アプリ開発をする上で決してメジャーな選択ではないと思いますが、効率的な開発を行なう上では有力な選択肢ではないかと思います。
色々とハマりどころはあると思いますが、少しずつ知見を溜めていけたら良いなと思います。

[ReactNativeを使った開発を行う上での選択肢]

1. Expo

Expoとは、ReactNativeでのアプリ開発を支援するためのプラットフォーム(SDK)です。
※ Expoの詳細については、色々な方が説明しているかと思うので割愛します。
特徴としてはExpoの機能で完結するアプリの場合、アプリの作成はJavascriptのみで完結します。
iOSAndroidでは、ビルドや開発にXCode(iOS)、AndroidStudio(Android)を使うのが一般的ですがExpoを使うとビルド作業自体もExpoサービス上で行ってくれます。
デメリットとしては、上記の通り基本的にiOSAndroidのネイティブコードを触ることができないためExpoSDKでできないことがやりたくなった場合は別途ejectを行い、ネイティブアプリの書き出しを行います。

プロジェクトの始め方は、ここを参照。

※ このすべてをExpoサービス上で行う開発をmanaged-workflowと呼ぶみたいです。

2. React Native

基本的なReactNativeでの開発で、iOSAndroidソースコード + ReactNativeライブラリを使って開発を行います。
一通りのセットアップは、react-native CLIツールが提供してくれており、その手順に従うとReactNativeでの開発が可能な状態でiOSAndroidのプロジェクトを作成することができます。
各アプリのビルドは、iOSAndroidの本来のビルドツールで行う必要があります。
Expoには提供されていないライブラリを使用したい場合や、Expoではできないようなネイティブコードに特化した機能をカスタマイズしたい場合はこの方法で開発することになります。

プロジェクトの始め方は、ここを参照。

3. React Native + Expo SDK

1 と 2をあわせたような方法です。
Expoから作成したライブラリをejectするときの選択肢の一つで、ExpoSDKで使用できるツール郡はそのまま使い続けるが、ビルドなどのワークフローは独自に行うという方法になります。
Expoプロジェクトを expo eject するときにXXXを選択した場合、ExpoSDKを組み込んだ状態のiOSAndroidのプロジェクトが出力されます。

? How would you like to eject your app?
  Read more: https://docs.expo.io/versions/latest/expokit/eject/ (Use arrow keys)
❯ React Native: I'd like a regular React Native project.
  ExpoKit: I'll create or log in with an Expo account to use React Native and the Expo SDK.
  Cancel: I'll continue with my current project structure.
  • 上記の選択肢でExpoKitを選んだ状態

この方法の利点は、ExpoSDKの使える機能を利用しつつ、Expoだけではできない機能のライブラリなどを組み込むことができるようになることです。

※ このExpoの機能を利用するフローをbare-workflowと呼ぶみたいです。

[どの方法を選択するか?]

業務で関わっているアプリは、2のReactNativeのみで作成されており、個人の趣味で作成したアプリは3のExpoSDKを組み込んだ状態で作成しました。
個人的には、3のExpoSDKを活用した方法が良いかと思っていますが、色々と判断の上自分たちにあった方法を選択するのが良いと思います。
3を選んで感じたことをいくつか書いていきます。
※ あくまで個人的な感想です。
(目的が明確であり、シンプルさと速度を重視するのであれば、1のExpoのみで開発するのが一番簡単だと思います。)

[良かったこと] OTA Updates(code push)

ReactNativeで開発するメリットの一つにOTA Updates(code push)があります。
これは、アプリストア(AppStore、GooglePlayStore)を介さずに、直接アプリをアップデートできる仕組みです。
簡単に説明すると特定の契機(アプリ起動時など)に最新のJSファイルをサーバからダウンロードして、現在動いているものと差し替えるというものです。
ReactNativeでこれを実現するためには、Microsoftが開発しているcode pushライブラリを使うのが一般的ですが、Expoでは標準で組み込まれています。
使い方も非常にシンプルで、Expoに機能がまとめられていることはメリットの一つではないかと思います。

[良かったこと] シミュレーターでの開発

ReactNativeでシミュレーターを使った開発を行なうときは、 iOSであれば react-native run-iosAndroidreact-native run-android を実行しますがExpoは expo start のみで両方のOSが繋がります。
また、詳しく検証してないので実際のところわかりませんが、シミュレータ自体の動きもExpoのほうが安定しているように感じます。(個人的な感想です)
ベースの技術は同じような気がするのですが、後発のExpoのほうが色々とうまくできているというのはあるのかもしれません。

[悪かったこと] ExpoSDK内で使用されているライブラリと別ライブラリで競合が発生した

具体的には、AndroidのExpoSDK内で使用しているokhttpという通信ライブラリがあるバージョンからExpo独自パッケージに変わり、依存しているその他のライブラリと競合が発生してビルドで苦労した。という内容です。
Androidではあるあるといえばあるあるなのですが、ExpoSDK自体が決して小さいライブラリではないのでこういった依存関係での問題はそれなりにあるのかなと思います。

[React Nativeでアプリを作る上で注意すること]

ゼロからアプリを作る上でいくつかハマったり、感じたことがあったので記載します。

iOSAndroidは、必ず同時に動作確認をする

僕の場合、まずはiOSだけで動作確認して開発をしており、「ある程度動いたらAndroidも確認するか」ぐらいの気持ちでいました。
そしてある程度作り上げた時点で、Androidでビルドしてみたいのですが全く動きませんでした。(ビルドがまず全然通らなかった)
ReactNativeは、クロスプラットフォームツールのためよほどのことがない限りは、外部のライブラリを比較的多く利用すると思います。
そのため、ビルド時の依存関係で問題が発生することは多々あります。
これはReactNativeに限った話してはないのですが、依存関係の問題は複数が同時に発生しているほど読み解くのが困難になり非常に辛いです。
ですので、iOSAndroidの動作確認は常に同時に行っておくべきでした。(ネイティブライブラリを利用したタイミングでは特に)
また、iOSAndroidでは描画システムが異なるため、片方できれいに配置されていても、もう片方では位置がずれているようなこともしばしばあります。
そういった点も踏まえると、常に両プラットフォームを確認しておくのが結果的に効率的かと思いました。

やりたいことが実現できるライブラリがないと開発コストが上がる

ReactNativeは、基本的はJSを使った開発になるのですが、各OS固有の機能やモバイルデバイス固有の機能を使う際にネイティブ層を意識した実装が必要になります。
(例えばカメラやGPS、Push通知など)
これらの多くの機能は、ReactNative自身やExpoが提供してくれてはいますが、その中に使いたい機能が存在しなかった場合は以下の選択肢になります。

  • ①.ネイティブ層(iOS,Android)とのブリッジを自分で実装し、各ネイティブ言語で使いたい機能を実装する
  • ②.3rdパーティ製のライブラリを探して、組み込む

①を選択する場合は、各ネイティブOSの実装知識が必要となるため多くの場合は②をまずは選択するかと思います。

そのため、ReactNativeを使った開発を選択する場合、「ライブラリをさがす作業」に多くの時間を使いがちになるなと感じています。
(今どきのモバイル開発はかなりのエコシステム化が進んでいて各ネイティブで開発をしていても基本的に誰が便利なライブラリを公開してくれていますが、ReactNativeの場合はモバイルエンジニア以外の人が始めることもあるので特にだと思います。)

それでも、どうしても機能が実現できなかった場合は①を選択するしかありません。
僕の場合は、iOSAndroidも一応実装できるのですが上記のようなことが起きたときに「これiOS(Android)ならそんなに難しくないのにReactNative上で両OSを意識して実装するのめんどくさいなぁ」と思うときが時々あります。


引き続き何かあれば、追記していきます。