贅沢な朝を過ごすようになった話

最近、贅沢な朝の過ごし方をしています。

夜に飲む回数を週1(以前は週3)に減らした事で浮いた時間と体力を、朝に投資してみました。


「会社のため」でなく「自分のため」に早起きする贅沢。


ガラガラの電車で背広姿のサラリーマンとは反対方向の街に向かう贅沢。


極上のエスプレッソを誰もいない早朝のカフェで楽しめる贅沢。


美味しい朝ごはんを食べに行くとだいたい予算は1,000円〜2,000円くらい。3,000円も出せば高級なホテルのモーニングビュッフェが楽しめます。(コスパ良い!)

起床 → 出社の間にイベントを1つ挟むと簡単にQOLがブーストできるので精神衛生上とても良いです。

それではここ数ヶ月で僕が食べに行ったモーニングのお店をいくつかご紹介します!

パンとエスプレッソと

東京都渋谷区神宮前3丁目4−9
表参道駅から徒歩5分

平日でも開店前から行列ができるお店です。フレンチトーストが絶品。たっぷりと蜂蜜をかけてお楽しみください。

テイクアウトもできるので通勤前にフラッと寄れるのもオススメ。

夕方には名物の鉄板フレンチトーストが楽しめます。

Le Pain Quotidien 芝公園

東京都港区芝公園3-3-1 東京プリンスホテル
御成門駅から徒歩1分

東京タワーのお膝元、芝公園にあるベルギーのパン屋さんです。

僕はいつもエッグベネディクトを注文するのですが、その他にもアボカドトーストやベルギーワッフル、グリエールチーズオムレツなどメニューは豊富。

また、備え付けのジャムバーで小皿にたっぷりとジャムを取ってウィートブレッドやバゲットにつけて楽しむこともできます。

東京タワーを見上げながらの朝ごはんを、是非一度味わってみてください!

bills 七里ヶ浜

神奈川県鎌倉市七里ガ浜1丁目1−1 WEEKEND HOUSE ALLEY
江ノ電 七里ヶ浜駅から徒歩2分

「世界一の朝食」と名高い海沿いのお店。

湘南の海を見ながら楽しむ朝食を求めて、始発に飛び乗って向かいました

トロトロのスクランブルエッグとジューシーなソーセージの組み合わせがたまりません。

甘いものがお好きな方には、名物のリコッタパンケーキがオススメです。

たまにはビーチを散歩してから仕事に行くのも悪くないかも。

ヨコハマ グランド インターコンチネンタルホテル オーシャンテラス

神奈川県横浜市西区みなとみらい1丁目1-1
みなとみらい駅から徒歩5分

和洋中が揃った絶品モーニングビュッフェです。

一流ホテルだけあって料理の質もサーブの質もとても高い!

お値段3,300円と安くはないですが、飲み会を1度スキップすればと思うと気分も軽くなります笑

サクサクのデニッシュとふわふわのオムレツが美味しかったです。

RISO CANOVIETTA

東京都千代田区丸ノ内1-9-1 JR東京駅構内 B1F グランスタ
JR東京駅改札内

東京駅の中で食べられるリゾット専門店。

熱々のリゾットを朝から味わっているとどうしても白ワインが飲みたくなりますが、グッと我慢。

朝一番の新幹線で東京に戻って来たときに、フラット立ち寄りたくなるお店です。

グッドモーニングカフェ 千駄ヶ谷

東京都渋谷区千駄ヶ谷1-17-1 東京体育館 プール棟 1F
千駄ヶ谷駅から徒歩3分

去る8/11に惜しまれつつの閉店を迎えた名店。

フレンチトーストやゆで卵のサラダだけでなく、ボリューム満点のスーパーモーニングセットもオススメです。

お腹が膨れたらその足で早朝の新宿御苑を散策しましょう。

御苑の真ん中にある大芝生でお昼寝するのが最高に気持ち良いのですが、3回くらい遅刻したことがあるので気をつけましょう。

一時閉店してしまったこちらのお店も、どうやらオリンピックの頃にはまた再開するとのことなので、またモーニングを楽しめる日が待ちきれません。

Ivy Place

東京都渋谷区猿楽町16-15 DAIKANYAMA T-SITE GARDEN
代官山駅から徒歩7分

代官山の蔦屋書店のお隣にある、緑に囲まれた落ち着いたカフェ。

平日の朝には出勤前のサラリーマンやOLの方が多いです。

蔦屋で本を買い、この店でゆっくりと読んでから出社するのも良いなー

crisscross

東京都港区南青山5-7-28
表参道から徒歩2分

女子力と糖分の塊のようなものを楽しめるお店。

フレンチトーストとパンケーキが絶品です。

テラス席も素敵ですが、夏の暑い時期は多少混雑はするものの店内がオススメです。

六本木グランハイアット The French Kitchen

東京都港区六本木6-10-3 グランド ハイアット 東京 2F
日比谷線 六本木駅から徒歩3分

六本木ヒルズ内、グランハイアットにあるお店です。

モーニングビュッフェでは、シェフが目の前で焼いてくれるオムレツを楽しめます。

コーヒーがおかわり自由なのでついつい長居してしまいました。

六本木でラグジュアリーな朝を楽しみたい時にどうぞ。

つるとんたん 新宿店

東京都新宿区歌舞伎町2-26-3 網元ビル B1F
新宿駅から徒歩7分

やっぱこれでしょ!

歌舞伎町で朝まで遊んだ後に食べるうどんは絶品。何度お世話になったか分かりません。

オールした次の日に仕事があってもエネルギーがチャージできるお店です。優雅さには程遠いけど笑

疲れた時の鉄板!!

最後に

20代の後半戦に突入してからというもの、普通に夜がしんどくなって来ましたが、東京は美味しい朝ごはんのお店がたくさんあって嬉しいですね。

これまで東側を中心に開拓してきたので、これからは西側のお店も探してみたいと思います。上野とか、浅草とか千葉の方とか。

割と衝動的に出かける事が多いですが、一緒に朝活してくれる人を募集しています。適当にTwitterとかで声かけてください。

ではでは

【翻訳】Sunsetting React Native

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を確認中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第四弾です。

これまで多くのチームがReact Nativeを信頼して今後も利用し続ける計画を立てていましたが、結論としてReact Nativeが私たちのゴールを達成することはできませんでした。継続してReact Nativeに投資を続けるための数多くの技術的な問題組織構造の問題に対して、私たちは解決策を見出せなかったのです。

この経験を活かして前に進むため、AirbnbではReact Nativeから漸次的に退いて全ての力をネイティブに再投資します。

目標達成の失敗

より早く動くこと

React Nativeが期待通りのパフォーマンスを発揮していた頃、エンジニアたちはかつてないスピードで開発を進めることができました。しかしこの一連の記事で触れている技術的な問題組織構造の問題によってフラストレーションが蓄積され、予見できなかった様々な遅延が多くのプロジェクトにおいて発生しました。

品質を保つこと

React Native自体の成熟度が上がったことや、私たちの中でより多くの知見が蓄積されたことなどで、近頃はかつて実現可能性すら分からなかった多くのことが可能になりました。Shared Element TransitionsやParallaxを作ったり、フレームレートの低下が頻繁に起きていた画面のパフォーマンスを劇的に向上させたりといったことです。しかしながら初期化処理や非同期なファーストビューの描画に関するものなどの様々な技術的チャレンジによって叶わなかったものがあるのも事実です。社の内外におけるリソースの不足により、これらの問題は一層難しくなりました。

Write Code Once Instead of Twice

私たちのアプリにおいてはReact Nativeの大部分が複数のプラットフォームで共有されているものの、そもそもReact Nativeが使われているのはアプリ全体のわずかな部分でしかありません。更に、プロダクトエンジニアの生産性を担保するためには大量のbridgingが必要になります。その結果として私たちは(2つではなく)3つ全てのプラットフォームに対する統合的な補助コードを作ることになりました。私たちはWebとネイティブにおけるコードシェアリングの可能性を信じ、実際にいくつかのNPMパッケージを共有することができましたが、それを除けば本当に意味のある"Write Code Once Instead of Twice"は実現しませんでした。

撤退計画

上記のようにReact Nativeは私たちが定めたゴールを達成することができなかったため、私たちに適した道具ではないということを結論づけました。目下、複数のチームと力を合わせて最適な移行プランを計画中です。既にReact Nativeを利用した全ての機能開発は取りやめ、高いトラフィックを持つ画面については年内を目標に大部分をネイティブに置き換え予定です。これらは必ずしもReact Nativeのみに責任があるわけではなく、予てより予定されていたスケジュール変更の影響もあります。私たちのネイティブインフラチームも2018年中はReact Nativeのサポートを行う予定です。2019年からは徐々にサポートを減少させ、起動時のランタイム初期化等のReact Nativeがオーバーヘッドする部分も削減してく予定です。

Airbnb社は、オープンソースの力と意義を信じています。私たちは積極的にOSSを利用するだけでなく、世界中の多くのプロジェクトにコントリビュートしており、React Nativeに関するものも公開してきました。社全体として徐々にReact Nativeから離れていくなかでReact Nativeレポジトリに対して十分なメンテナンスが行えなくなってしまいますが、コミュニティにとってのベストを考えていくつかのプロジェクトをReact Native Communityに移譲します。既にreact-native-mapsについては取り組みが始まっており、native-navigationlottie-react-nativeについても対応予定です。

そんなに悪くなかったよ?

私たちのゴールを達成することこそ叶いませんでしたが、React Nativeに触れていたエンジニア達は概ね肯定的な意見です。内訳をみると、

  • 60%が「素晴らしい開発経験だった」と感じた
  • 20%がやや肯定的
  • 15%がやや否定的
  • 5%が強く否定

となっています。また63%のエンジニアがまたチャンスがあればReact Nativeを選択すると答え、74%が新しいプロジェクトにおいて選択肢に含めると答えました。注目すべき点は、これらの調査対象が全て一度はReact Nativeを使っていたエンジニアであるということです。

彼らは80,000行ものプロダクトコードを産み出し、220もの画面を作り、40,000行ものJavaScriptのインフラストラクチャを書いたエンジニアです。参考のために触れておくと、私たちはネイティブにおいてはこの10倍ものコードと4倍もの数の画面をそれぞれのプラットフォームで開発しています。

React Nativeは成熟してきている

この一連のポストは今日の時点における私たちのReact Native体験を振り返るものです。ですがFacebookやReact Native CommunityのメンバーはRNがハイブリッドアプリでもスケールするよう身を砕いています。かつてないスピードでReact Nativeは発展しているのです。昨年には2,500ものコミットが反映され、Facebook自身も私たちが直面したような問題を真摯に受け止めています。私たちがこれ以上React Nativeに投資することはありませんが、これからの開発を見守れることを楽しみにしています。なぜならReact Nativeの成功は私たちのプロダクトを使ってくれる世界中の人々の幸せにつながるのですから。

学び

私たちは急速に発展を続けるアプリケーションにReact Nativeを組み込みました。その中で直面した問題の多くは、私たちがハイブリッドモデルのアプローチを選択したことに由来します。しかし小さな会社では十分なリソースが無く、このスケールの会社だったからこそ得られたことや解決した問題もあるでしょう。React Nativeをネイティブとシームレスに統合することは可能です。ですが難しいことです。React Nativeを使う全ての会社が、そのチームの構成や、既存のアプリや、プロダクトの要求や、React Nativeの成熟度によってユニークな経験をするのだろうと思います。

全てのピースがはまった時(そういう場面はたくさんありました)、React Nativeは開発のイテレーションスピードや品質、そして開発体験全体において私たちの期待通りもしくは期待以上のパフォーマンスを発揮してくれました。そういう時には、私たちはモバイル開発自体を変革させる瀬戸際に立っているのだというような気持ちになりました。もちろんそのような素晴らしい体験も是非していただきたいですが、改めてその恩恵と痛み、そして今の優先事項やエンジニアリング組織のリソースを比較したとき、それは私たちにふさわしいものではないと結論づけました。

新たなプラットフォームの採用はとても大きな決断で、あなたのチームが抱える様々なユニークなファクターによって決まります。私たちが経験したことやReact Nativeを手放すことになった理由は、あなたのチームには当てはまらないかもしれません。実際にたくさんの会社がReact Nativeによる素晴らしい体験を継続しており、多くの人々にとってはいまだにベストなツールかもしれません。

私たちはこれまでもネイティブに投資をし続けていましたが、React Nativeから離れることでかつてないほどのリソースをより良いアプリを作ることに投下できます。次の記事で私たちの新たなネイティブに関する取り組みを知ってください!

その他の記事

  • Part 1: React Native at Airbnb
  • Part 2: The Technology
  • Part 3: Building a Cross-Platform Mobile Team
  • Part 4: Making a Decision on React Native(本記事)
  • Part 5(未完了): What’s Next for Mobile

【翻訳】React Native at Airbnb: The Technology

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を確認中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第二弾です。

React NativeはAndroid, iOS, Webで横断的に動作する、それ自体が比較的新しく急速に発展しているクロスプラットフォームフレームワークです。2年間に渡って使ってきた今、React Nativeは多くの点において革新的なツールであると自信を持って言えます。それはモバイル開発におけるパラダイムシフトであり、私たちはReact Nativeが掲げるゴールから多くの恩恵を受けることができました。しかしその利点を得るために多くの痛みが伴ったことは無視できません。

上手くいったこと

クロスプラットフォーム

React Nativeを利用することによる一番の利点は一度書いたコードがAndroidでもiOSでも動作するということです。React Nativeで実装した機能の多くでは95-100%のコードを共有することができ、 プラットフォームに依存したファイル(*.android.js/*.ios.js)は0.2%にすぎませんでした。

共通のデザイン言語システム(DLS)

私たちはDLSと呼ばれるクロスプラットフォームデザイン言語を開発しており、AndroidiOS、React Native、Web、それぞれのバージョンがコンポーネントごとに存在しています。クロスプラットフォームに開発を進める上で、一貫したデザイン、コンポーネント名、そして画面を定義できる共通のデザイン言語を持つことは当然の帰結でした。

しかし同時に必要に応じてプラットフォーム固有のデザインを適用することもまた可能でした。例えばAndroidにおいてToolbarを利用するがiOSではUINavigationBarを使う、Andoroidではプラットフォームのデザインガイドラインに適さないdisclosure indicatorsを隠すなどといったことです。

私たちはネイティブのコンポーネントをラップするのではなく、React Nativeでコンポーネントを書き直す方法を選択しました。なぜならその方が個別にプラットフォーム固有のAPIを叩く上で信頼性が高く、React Native上での変更をテストする手段に詳しくないネイティブエンジニアのメンテナンスにおけるオーバーヘッドを削減できるからです。ただしこのアプローチはネイティブとReact Native間でのバージョンの乖離を引き起こすこととなりました。

React

Reactが最も愛されるWebフレームワークと呼ばれるのには理由があります。シンプルかつ強力で、より大きなコードベースへスケールしやすいからです。特に私たちが気に入っている点としては、

  • Components: 適切に定義されたpropsとstateによってReact Componentは開発における関心の分離を実現します。これはReactのスケーラビリティにおける大きな要因です。
  • 簡潔なライフサイクル: Androidと(多少はマシですが)iOSのライフサイクルは非常に複雑なことで知られています。適切に動作するリアクティブなReact Componentはこの問題を根本的に解決するため、React Nativeの学習をAndroidiOSのそれと比べて非常に容易にしています。
  • 宣言的: Declarative(宣言的)であるというReactの特徴は、内部のStateとUIの整合性を保つ上でとても役に立ちます。

検証スピード

React Nativeを利用することでアプリケーションの変更を即座に確認できるhot reloadingを活用することができます。ビルド時のパフォーマンスこそネイティブアプリに軍配が上がりますが、開発・検証スピードにおいてはReact Nativeの足下にも及びません。最速で15秒もあればネイティブアプリをコンパイルすることはできますが、長い時にはビルドに20分ほどかかることもあります。

インフラへの投資

私たちはネイティブのインフラに対して広い範囲でのIntegrationを実現しました。'networking', 'i18n', 'experimentation', 'shared element transitions', 'device info', 'account info'というコア機能をはじめとした多くの機能が個別のReact Native APIとしてラップされました。既にあるAndroidiOSAPIをReactのために整合性を持たせたり正規化する必要があったため、それらのBrdigeはとても複雑なパーツとなりました。高速な開発サイクルの中でこれらのBridgeを常に最新の状態に保つ作業が必要になりましたが、インフラチームがこの部分に投資してくれたことによってプロダクト開発がずっと容易になりました。

このインフラ部分への大きな投資がなければ、React Nativeによる開発はもっと中途半端なものなっていたでしょう。React Nativeを既存のアプリにつっこむためには、このような投資が必要不可欠だろうというのが私たちの結論です。

パフォーマンス

React Nativeにまつわる最も大きな心配事の一つがパフォーマンスの問題です。ですが実際はほとんど問題になることはなく、React Nativeで実装した多くの画面がネイティブと遜色なく動作しました。パフォーマンスというものは一面的に捉えられがちです。ネイティブエンジニアがJSに対して「JAVAより遅い」と考えているのをよく見かけますが、ビジネスロジックlayoutをメインスレッドから分割することで描画のパフォーマンスが向上することは多々あります。

パフォーマンスの問題が発生することもありましたが、大抵は過度な描画によるものでshouldComponentUpdateremoveClippedSubviewsを活用したりReduxの使い方を改善することで和らげることができました。

しかしながら初期化処理と最初の描画時間に関するパフォーマンスは低くReact Nativeで作った起動画面やディープリンク、画面回遊時のTTIなどに大きな影響を与えました。それに加えてYogaがReact Native coponentをネイティブのviewに変換するため、スクリーンフレームの低下時にデバッグするのが難しいという問題もありました。

Redux

StateとUIの整合性を保ちやすい、画面をまたいだデータの共有が簡単に行える等の有用性から私たちはReduxを採用しました。ですがReduxは悪名高いboilerplateで知られ、学習の難易度も高いです。一般的なテンプレートを生成するジェネレータも用意しましたが、ReduxはReact Nativeで開発する上で最も難しい部分であり混乱を招きやすい部分であることに変わりはありませんでした。React Nativeに限った問題ではありませんが。

ネイティブの支え

React Nativeの中で起きる全てのことはネイティブのコードにBridgeできるため、開発を初めた時点では予期しなかった多くのことが可能になりました。

  1. Shared element transitions: 私たちはAndroidiOSのネイティブコードと連携した <SharedElement>コンポーネントを開発しました。これはネイティブとReact Nativeのスクリーン間でも利用できます。
  2. Lottie: AndroidiOS向けのライブラリをラップすることでLottieをReact Native上で動かすことが可能になりました。
  3. ネットワーク機構: React Nativeは既にあるネイティブの通信スタックとキャッシュ機構を利用します。
  4. その他のコアインフラ: Networkingだけでなく、'i18n'や'experimentation'のようなその他のネイティブインフラもラップすることでReact Nativeからシームレスに利用できます。

静的解析

AirbnbはWebでのeslintの利用について確固とした実績を持っていますが、prettierを導入したのは私たちのプラットフォームが社内では初めてでした。prettierはPull Requestにおける細かな指摘やミスを軽減するのにとても有効で、Webインフラチームでは活発に試されています。

また描画にかかる時間とコストを解析することで、改修の優先度が高い画面を調べています。

React NativeはWebと似ているだけでなくそのさらに先を行くプラットフォームであるため、新しいアイディアを試すのに持ってこいです。React Nativeのために開発した多くのツールやアイディアが今ではWebにも持ち込まれています。

アニメーション

React Nativeのアニメーションライブラリのおかげで効果的なアニメーションを実装可能になり、スクローリングやパララックスなどインタラクションドリブンなアニメーションも手に入れました。

オープンソース

React NativeではReactとJavaScriptという巨人の肩に乗ることで、redux,reselect, jestといった膨大な数のJSプロジェクトの恩恵を受けることができます。

Flexbox

C言語で書かれたクロスプラットフォームなライブラリでありFlexbox APIによるレイアウト計算を行うYogaをReact Nativeでは利用しています。はじめこそアスペクト比が使えないなどYogaの機能的制限に悩まされましたが、その後のアップデートで解決されました。flebox froggyのような楽しいチュートリアルもオンボーディングで活躍しています。

Webとのコラボレーション

開発が進むにつれて最近ではWeb, iOS, Androidの開発を一度に行えるようになりました。WebでもReduxが使われていることからWebとネイティブで広範囲に渡るコードを、特別な調整なしで共有できることに気が付いたのです。

上手くいかなかったこと

React Nativeの未熟さ故の問題

新しく、野心的で、急速に発展してはいますがReact NativeはAndroidiOSに比べてまだまだ未成熟なプラットフォームです。多くの状況でReact Nativeは上手く機能する一方、その未熟さ故に些細な問題を解決するのがとても難しくなってしまうことがあります。残念ながらこれらのケースは予測が難しく、ワークアラウンドを行うのに数時間で終わることもあれば何日もかかることもあります。

Forked React Nativeのメンテナンス

React Nativeは未成熟であるため場合によってはソースコードに修正を加える必要があります。すぐに修正を反映するためにはReact Native本体にコントリビュートするのみでなく、Forkした独自のレポジトリを用意して管理する必要がありました。この2年間でReact Nativeに対して約50個ほどコミットを積みましたが、これによってReact Nativeのアップデートが恐ろしく大変なものとなったのです。

JavaScriptツール

JavaScriptは動的型付けの言語です。型安全でない言語を扱うことはスケールが難しいだけでなく、型のある世界からやってきたネイティブエンジニアとの争いの元となりました。彼らは型の問題がなければよりReact Nativeの学習に興味を示してくれたでしょう。

私たちはflowの導入を試みましたが、まるで暗号のようなエラーメッセージに開発者のフラストレーションはたまる一方でした。TypeScriptも調査はしましたが、既にあるbabelmetro bundlerとの統合に問題があります。そのような状況ではありますが、今後も私たちはTypeScriptの調査を継続していくつもりです。

リファクタリング

JavaScriptという型のない言語を扱った結果、リファクタリングがとても大変な作業になり多くのエラーが吐かれることとなりました。props名の変更、特に複数のコンポーネントにまたがって継承される onClickのような広く使われるpropsを正確に変更する作業はまるで悪夢のようでした。更に悪いことにコンパイルは通るのにプロダクション環境で壊れるリファクタ、静的解析を適用するのが難しいリファクタなどもありました。

JavaScriptCoreの不安定性

React Nativeのトリッキーな特徴としては、それがJavaScriptCore environmentで実行されるということです。それによって以下のような問題に直面しました。

  • iOSは初期状態で独自のJavaScriptCoreを持っているため動作も概ね安定しており、大きな問題はありませんでした。
  • Androidは自前のJavaScriptCoreを持たないため、React Nativeが自身のものをバンドルすることで実行環境が作られます。問題なのはこのランタイムがとてつもなく古いものであるということです。結果的に私たちは新たに自前で新しいJSCをバンドルしてやる必要がありました。
  • React Nativeはデバッグ時にパワフルなChrome Developer Toolsに接続します。素晴らしい!ですがデバッグモードに入ると同時に、React NativeのコードはChromeのV8エンジンで実行されるようになります。99.9%のケースでは特に問題はないのですが、ただ一度だけ、 toLocaleStringメソッドがAndroidではデバッグモードでしか動かないという問題に引っかかりました(iOSは大丈夫でした)。どうやらAndroidJavaScriptCoreにメソッドが含まれておらず、そこでエラーも吐かずに落ちていたようです。当然デバッグ時に利用するV8環境では動作していました。このような問題に対処できる深い技術的知識がなければ、何日も現場のエンジニア達は悩まされることになるでしょう。

React Native向けのオープンソースライブラリ

任意のプラットフォームについて学び、習熟するのには長い時間がかかります。多くの人は1つまたは2つのプラットフォームについてのみしか理解してないと言えるでしょう。mapやvideoといったネイティブとのbrdigeを持ったReact Nativeライブラリを開発するには3つ全てのプラットフォーム知識が求められます。残念ながら多くのReact Native向けオープンソースライブラリの開発者は十分な数のプラットフォーム知識を有しているとは言えないでしょう。それはAndroidiOSどちらかのプラットフォーム上では動作が不安定になることを意味します。

Android向けの多くのReact Nativeライブラリではパッケージの読み込みにmavenではなくnode modulesの相対パスによる記述を要求しますが、これはコミュニティの期待する品質に比べて安定性が低いやりかたです。

インフラの二重管理と機能開発

私たちは長年に渡ってAndroidiOSにおけるネイティブのインフラストラクチャを構築・蓄積してきましたが、React Nativeに向けて全ての既存のインフラに対するBridgeをゼロから作成する必要がありました。つまりエンジニアが新しい機能を開発する際に、よく理解していないプラットフォームに対しても自らの手でBridgeを用意するか、誰かがそれを作ってくれるまで待つ必要があったのです。

クラッシュレポート

私たちはネイティブランタイムでのクラッシュレポートにBugsnagを利用しています。AndroidiOSのどちらのプラットフォームでも大抵は動作する一方で、あまり信憑性は高いとは言えず特定にプラットフォームに向けたオプティマイゼーションも必要でした。React Nativeは新興であるが故に、私たち自身の手でsource mapアップロードのようなインフラを大量に作成したり、BugsnagがReact Nativeで起きた問題のみをトラックできるようなフィルタリング機能を追加する必要がありました。

このように多くのインフラレベルの機能をReact Nativeに実装しなければいけない状況下であるため、クラッシュしたのにレポートが送信されない、source mapが適切にアップロードされないといった問題に悩まされることになりました。

もう一つ付け加えると、ネイティブとReact Native間でスタックトレースは別れてしまうため、双方を跨いだ問題のデバッグはとても大変なものになるでしょう。

ネイティブブリッジ

React Nativeにはネイティブと通信するためのbridge APIがあります。このAPIは期待どうりの動作をしてくれるものの、実装するのがものすごく面倒です。まず初めに3つのプラットフォーム向けのそれぞれの開発環境を適切に設定する必要があります。JavaScriptから返ってくるデータ型が予測不可能という問題もあります。例えばinteger型はしばしばstring型にラップされてしまい、bridgeを通ってみるまでどうなるのか分かりません。またAndroidではクラッシュするのにiOSではフィードバックもなく落ちることがあります。私たちは2017年の終わりにかけてTypeScriptの型定義ファイルからbridgeコードを自動生成する方法に取り組みましたが、その時にはもう遅すぎました。

初期化の時間

React Nativeがファーストビューを描画するには、まずその前にランタイムを初期化する必要があります。残念ながら私たちほどの規模になると、たとえそれがハイエンドデバイスであっても数秒かかってしまいます。このような問題があるなかでReact Nativeをアプリの起動画面に採用することはほぼ不可能です。私たちはアプリの起動時にReact Nativeの初期化を行うことでファーストビューの描画にかかる時間を最小化しました。

ファーストビューの描画時間

ネイティブの場合とは異なりReact Nativeでファーストビューに必要な情報をあつめて描画するためには、メインスレッド -> JS -> yogaレイアウトスレッド -> メインスレッドというサイクルを実行する必要があります。ファーストビューを描画するまでの平均時間はiOSで280ms、Androidで440msでした。AndroidではpostponeEnterTransition APIを利用しています。通常はshared element transitionにおいて描画までのディレイを適用するために使われるものです。iOSにおいてはNavBarの設定にReact Nativeだと時間がかかりすぎるという問題がありました。最終的に私たちはnavbarの設定が読み込まれるまではインタラクションが発生しないよう、全てのReact Nativeでのページ遷移に50msのディレイをかけることにしました。

App Size

React Nativeによるアプリケーションサイズへの影響も無視できません。Androidの場合、React Nativeのトータルのサイズ(Java + JS + Yoga含むネイティブライブラリ + JavaScript Runtime)はABIごとに8MBとなりました。x86とarm(32bit only)を含めたAPKなら12MBほどになるでしょう。

64bit

この問題により、今の所はまだAndroidに向けて64bitのAPKを配信できていません。

ジェスチャー

タッチコントロールに関するサブシステムはAndroidiOS間での違いが大きすぎることもあり、それらを統合するAPIを開発することはReact Nativeコミュニティ全体にとって大きな課題です。そのようなこともあり現在Airbnbでは、複雑なジェスチャーを要求する画面ではReact Nativeは利用していません。しかしながらreact-native-gesture-handlerのv1.0が最近リリースされるなど、まだ取り組みは活発なようです。。

リスト表示

FlatListのようなライブラリが登場したことでReact Nativeでもこの分野が発展してきているようです。ですがそれはまだAndroidRecyclerViewiOSUICollectionViewには到底及びません。スレッドの機構により多くの制限がなかなか解決されないでいます。Adapterの持つデータには同期的なアクセスされないため、高速にスクロールしていても非同期でViewを描画することも可能なはずです。テキストもiOSでは非同期で取得されるため、事前にCellの高さを計算することが難しいです。

(* 訳注: あまり意味が理解できておらず申し訳ないです。)

React Nativeのアップグレード

React Nativeにおけるほとんどのアップグレード作業は難しくありませんが、とても大変なケースがいくつかありました。具体的な例を挙げるとReact Native 0.43(2017年4月リリース)からReact Native 0.49(2017年10月リリース)へのアップグレード作業では、前者がReact 16のα版、後者がβ版を利用していた関係でほぼ不可能とも思える作業になりました。多くのReactライブラリがWebを想定して設計されているため、最新版のReactへの対応がなされておらず手こずることとなりました。2017年中頃のインフラチームはこの依存解決の問題に追われ、結果的に大くのコストが費やされたこととなります。

アクセシビリティ

2017年に私たちはアクセシビリティに関する大幅な改修を行い、ハンディキャップを抱えた人たちが最適なリスティングを見つけ、予約できるように努力しました。しかしながらReact NativeのアクセシビリティAPIにはいくつもの穴があります。最低限のアクセシビリティ要件を満たすためだけでも、私たちはForkしたReact Nativeをメンテナンスして修正をマージする必要がありました。AndroidiOSならば1行加えるだけですむような修正でも、React Nativeでの実装方法を考え、変更を加え、React Native Coreに修正を出してケアするのには膨大な時間がかかりました。

やっかいなクラッシュ

私たちはいくつかの修正が難しい奇妙な問題にもぶつかりました。例をあげるとこちらの@ReactPropに関する問題を現在も調査中で、同じ端末同じソフトウェア上であっても問題を再現・究明できずにいます。

Androidでのプロセスの永続化

Androidは頻繁にバックグラウンドプロセスをリフレッシュしますが、その対策としてアプリケーションバンドルにstateを同期的に保存することが可能です。しかしながらReact Nativeにおいては全てのstateに対してJSからしかアクセスできないため、この同期的な保存を利用することができません。もしできたとしてもReduxにはシリアライズ可能なデータと不可能なデータが混在していますし、savedInstanceStateの容量では足りない大きさのデータも含まれるため、どちらにせよプロダクションでクラッシュしてしまいます。

その他の記事

  • Part 1: React Native at Airbnb
  • Part 2: The Technology(本記事)
  • Part 3: Building a Cross-Platform Mobile Team
  • Part 4: Making a Decision on React Native
  • Part 5(未完了): What’s Next for Mobile

【翻訳】React Native at Airbnb

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を得ている最中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第一弾です。

10年前にAirbnbが立ち上がった頃、スマートフォンはまだまだ未熟なものでした。それから時が経ってより多くの人々が世界を旅するようになったこともあり、今や私たちの生活においてスマートフォンは欠かせない道具になっています。

旅行中はモバイルデバイスが数少ない、もしくは唯一の通信デバイスになるということは往往にしてあります。世界トップレベルのアプリを開発することは、何百万人という人々に新しい旅のカタチを提供する我々のようなコミュニティにとってとても重要なことなのです。

2008年に私たちが最初のゲストをRausch Street(訳注 Airbnb創業者のアパートメントがあった場所)に迎えた時から、年間のモバイルからの予約件数はゼロから何百万という数字に増加しています。私たちの提供するアプリによってホストは簡単に自分のリスティング(訳注 Airbnbに掲載している物件)を管理できるようになり、また旅行者も新しい旅のアイディアを見つけられるようになりました。

このような急速なモバイル体験の普及に伴って、Airbnbでは100名以上のモバイルエンジニアと共に新機能の開発や既存の機能の改善に取り組んでいます。

React Nativeへの投資

私たちはAirbnbを利用するホストとゲストにとってより良い体験を提供し、また我々自身の質の高い開発体験を可能にするような新しいテクノロジーを常に検証しています。2016年の私たちにとって、その答えの1つがReact Nativeでした。その頃から我々はAirbnbのビジネスにとってモバイルというものが重要な位置を占めることを理解していましたが、単純にモバイルエンジニアの数が目標の達成に対して不足していたのです。そのような状況下で我々はその代替となるような選択肢を模索し始めました。

AirbnbのWebサイトは主要部分がReactで作られています。AirbnbにおいてReactは高いパフォーマンスを発揮し、誰からも好かれていました。そこでReact Nativeを採用することでクロスプラットフォームで高速でコードを配信できるだけでなく、より多くのエンジニアがモバイル開発に取り組む機会になると思ったのです。

React Nativeに対して投資を始めた時点で、私たちはリスクがあることを知っていました。コード資産を統一する可能性もあればバラバラにしてしまう可能性もある新興のプラットフォームを導入しようとしていたのですから。React Nativeに投資すると同時に、正しい使い方をしたいと私たちは思っていました。React Nativeを導入する上で私たちが掲げたゴールは以下の通りです。

  1. 組織全体の動きを加速する
  2. ネイティブと同等の品質を保つ
  3. モバイル向けのコードは1度しか書かない。2度は書かない
  4. 開発体験を向上させる

私たちの経験したこと

この2年間、実験的に始まった取り組みはより本格的なものになってきています。 'shared element transitions', 'parallax', 'geofencing'といった複雑なネイティブの機構だけでなく、 'networking', 'experimentation', 'internalization'といったネイティブが提供するインフラへのbridgeを可能にする強力なintegrationを私たちは開発しました。

私たちはこれまでに数多くのAirbnbにとって重要な役割を果たすプロダクトをReact Nativeでローンチしています。ExperiencesというAirbnbにとって全く新しいビジネスだけでなく、レビューからギフトカードに至るまで何十もの機能がReact Nativeによって実現しました。これらの多くはまだ私たちが十分な数のネイティブエンジニアを有していない時代に開発されたものです。

それぞれのチームごとにReact Nativeを通して体験したことは異なります。技術的な問題や組織的な問題は残っているものの、現時点でReact Nativeは素晴らしいツールだと言えるでしょう。このシリーズではより詳しくReact Nativeの開発中に体験したことや、私たちのこれからの取り組みについて紹介します。

パート2では技術的な側面からReact Nativeにおいて上手くいったこと、そうでなかったことを挙げています。

パート3ではクロスプラットフォームなモバイルアプリを開発する上で直面した組織的な問題について紹介します。

パート4では今日におけるAirbnbとReact Nativeの関わり方と今後について触れています。

パート5(未完了)ではReact Nativeで開発する中で学んだことがどのようにネイティブで活きるかを書いています。

修行編 - 12日目

進捗ほぼありません。

やったこと

1. Rustフレームワークの調査 & お勉強

Ironが最初に手をつけるものとしては一番良さそうですね。情報もたくさん転がってるし。

2. Chrome Extensions入門

なぜかちょっとしたChrome拡張が作りたくなってドキュメント読んだり manifest.json書いてました。

画像用意するのが面倒で中断してしまいましたが思ったより手軽にDOM制御も出来て良いですね。

3. 会食

以前一緒にNuxt Meetupも主催した某社のエンジニアさん達とランチへ。

「社長がエンジニアの論理理解してるのすごい」「Nuxt使ってる会社で知名度No.1目指してるやつ、もう達成してるのでは?」

みたいな話をしてました。業界のドメイン知識は全然ないので恐縮ですが、チームとしてとても魅力的だなーと勝手に前から思ってます。

今度Tシャツもらいに行きたいです!

4. 青山探訪

用事があったため初めて青山学院大学にお邪魔して、ついでにその周辺を散策してきました。

渋谷から徒歩15分くらいなので歩くにはちょうど良いですね。

青学のキャンパスからはどこか同志社感を感じました。

factory.cr

青山ブックセンターで本を買ってから立ち寄ったのがこちらのfactoryさん。電源とWi-FIが完備されているのに加えてフカフカのソファーが作業スペースに最高でした。

残念ながら今月で閉店してしまうようなので、もう少し早く出会いたかったです。

5. 居酒屋ひとり飯

うちのシェアハウス御用達の駒沢魚庵 直で晩御飯のソロプレイをしました。

tabelog.com

お一人様も歓迎してくれる雰囲気だったのでとても入りやすかったです。

オススメはなんと言っても大将の寿司盛り!ネタのセンスも質も良く、近所でこの味が楽しめるのかーと嬉しい気持ちになります。

調子に乗っていろいろ頼んでいたら6k円くらいになったので、あまりハマりすぎないように注意。

6. Ninteno Direct at E3

MS、Sonyと来て本日は任天堂のプレゼンテーションでした。

www.nintendo.co.jp

深夜1時からライブ配信を視聴。内容てんこ盛りで脳みその処理が追いつきません。

特に印象に残ったものは以下。

スマブラやばいですね。昨日冗談で「オレ、アイスクライマー使うからwww」という話をしていたら本当に登場してビビりました。

ビッグブルーで8人対戦するのが楽しみで仕方ないです

明日やること

  • 面談
  • 打ち合わせ
  • Rustアプリケーションの立ち上げ
  • 明後日の準備

論文読んだり頑張ります。それでは良い水曜日を!