"最も使われているサービスのひとつを iOS Native から React Native に作り変えた" というアナウンスメントを出し話題となった Shopify で、まさにその内容を扱った React Native の meetup があり、参加してきたので内容と所感をまとめました。
React Native is the Future of Mobile at Shopify
React Native で書き換えた話はしばらく前にアナウンスしていたのですが、Shopify のブログで詳細が紹介されていました。
かいつまんで概要を書くと
- Shopify はもともと Web(React)が強く、また React Native に強い会社を買収したこともあり、その技術ノウハウを Mobile で活かすために 3 つのプロダクトで React Native を採用した(書き換えまたは新規実装)
- スペックの低い端末でも性能的に問題なく、コードベースは 95-99%共通化された
- Tooling など会社としてコミュニティに積極的に貢献していく
ということで、技術観点の具体的内容にはほとんど触れられてません。今回の meetup はそこをカバーする内容でした。
発表内容
発表をパシャパシャ撮りつつメモをとったので順番に説明します。
検証/導入フェーズ
彼らが React Native を導入したアプリはオンライン注文をトラックするArriveというアプリです。2017 年の最初のリリース時は iOS のみで、Swift で実装されていました。2018 年末から技術検証を始め、2019 年初頭から開発開始 ~ 4 月に iOS をリリースし、その後 8 月に Android 版をリリースしたそうです。
まずは導入にあたってパフォーマンス的に問題がないか検証したそうです。iOS と全く同じ画面を一つ作り、ユーザーを連れてきてユーザビリティテストを行った結果、ユーザーには全く差が見分けられなかったとのこと。
技術スタック
当然のように Typescript は使ってましたね。ネットワークリクエストは Apollo GraphQL です。
ステート管理は redux/mobx といったライブラリは使わず Apollo-Cache に全部任せているそう。最近この組み合わせはトレンドですね。
特にネイティブレベルのアニメーションに力入れているそうで、 software mansion の react-native-reanimatedなどネイティブ駆動のアニメーションライブラリを導入しているとのこと。react-native-reanimated はうちの会社でも使っていて、宣言的にアニメーションを記述できる点がよいです。
こんな感じ↓に Butterly slick(ぬるぬる)なアニメーションだそうです(ここでみんな拍手)
Butterly slick animation running on React Native
— Tomoaki Imai (@tomoaki_imai) 2020年1月30日
Shopifyアニメーション周りに力をいれてるそうで、アプリ、ぬるぬるアニメーションでした pic.twitter.com/N8NIpO1tlk
React Native がもたらした効果
95% のコードがシェアされ、当然ながら全く同じ機能性を実現できているそうです。コードベースの可読性が高いためにエンジニアのオンボーディング期間が非常に短いことや、 Web の技術スタック(テストや GraphQL周りとか)が活用できていることなど開発チーム観点でのメリットは非常に大きいとのことでした。
2 weeks release cycle は React Native 使っているならもっとアグレッシブに出せそうな感じもしますね。
途中でやめたこと
導入したもののうまくいかずやめたこともいくつか紹介していました。
Apollo の @client
ディレクティブはそのひとつ。 @client
ディレクティブは GraphQL 経由でローカルキャッシュにアクセスする機構ですが、いちいちアクセスするために Resolver を実装したり手間がかかって仕方がないので、今は直接 AsyncStorage にアクセスしているそうです。
これは納得感があって、React Native + GraphQL の構成だと関心の分離を意識したディレクトリ構成の検討を重視しつつ、ローカルデータやパーミッションの付与などネイティブに触れるAPIは柔軟にアクセスできるようにしたほうがスピード落とさず開発できるなと最近思っています。
Apollo の cache がボトルネックになるというのは意外でした。理由として cache の read/write が synchronous に行われるので処理がブロックされることがあるらしい。曰くこれは Apollo がもともと Web で使われる前提で実装されているからだと。なので Shopify では cache するクエリはかなり慎重に選んで利用している。
HOCs は当初、複数の GraphQL のリクエストを compose するために使っていたそうですが、イベントハンドリングが複雑になったため Hooks に書き換えたそうです。 Hooks は可読性の観点から相当いいらしい。この辺まだ詳しくないけど Apollo の apollo-hocs
は deprecatedされてるし、それでよさそう。
追加で登壇者に聞いたこと
発表後ネットワーキングの時間があったので登壇した Shopify のエンジニアに気になったことを色々聞いてみました。
Android のリリースが 4 ヶ月後だったのはなんで?
経営上の理由で、iOS のクオリティをあげることにフォーカスしていた。実際のところ着手して 1 ヶ月ほどでリリースした。
Android と iOS の 5%の違いは?ネイティブ実装もあるの?
サインイン周りの実装などが違う。Google Sign in と Apple Sign in でトークン取得方法が異なるのでネイティブで実装している。
@client directive やめたというけど複雑なローカルステート管理はないの?
実は自前でステートを管理するライブラリを作っていて画面観のデータの受け渡しに使っている。
GraphQL はどこに書いてるの?Component ファイル内?
graphql-importを使っているので、GraphQL はひとつのディレクトリで管理している。
その他の発表
実は他の発表(ゲームアプリに RN を導入した知見とか)もあったのですが、目新しい話はなかったので割愛。Twitter の React Native for Web をなぜ導入したかの話は面白かった。
React Native for Web @twitter
- Twitter web app に React Native for Web を採用した話
- Twitter webはもともとScalaで書かれていた。ボタンを丸くするためにインターンがひと夏かけたレベルで複雑化していたらしい。誰もが書きやすいもので置き換えることを検討した結果RN for webにたどり着いた
- Accessibility 仕組みが標準でサポートされている。Twitter は Accessibility をとても重視するらしい。
- 可読性が高く、コード量が削減できる。ボタンにアクセシビリティを実装するコード量がReactの1/3で済むとのこと
- CSS-in-JS の恩恵:React Native for Web を使うことでスタイルが JS で実装されることになり、コード最適化(minimization, 使われていないコードの排除)が可能となる
その他もろもろ
- みんな興味あったのか立ち見が出るくらいぎゅうぎゅう満員でした。
- Shopify はトロントに大きな開発拠点があるらしい。
- Native エンジニアを積極的に採用しているそうですよ!