メインコンテンツにスキップ

"engineering" タグが付いた投稿 26 件

すべてのタグを表示

React NativeでTwitterのアプリ読み込みアニメーションを実装する

·11 分で読めます
Eli White
Eli White
Metaのソフトウェアエンジニア

TwitterのiOSアプリには、私がとても気に入っている読み込みアニメーションがあります。

アプリの準備ができると、Twitterのロゴが楽しく展開し、アプリが表示されます。

React Nativeでこの読み込みアニメーションを再現する方法を見つけたいと思いました。


どのように構築するかを理解するために、最初に読み込みアニメーションのさまざまな部分を理解する必要がありました。微妙な違いを見る最も簡単な方法は、速度を落とすことです。

構築方法を理解する必要がある主要な部分がいくつかあります。

  1. 鳥の拡大縮小。
  2. 鳥が成長するにつれて、下にアプリを表示する
  3. 最後にアプリを少し縮小する

このアニメーションを作成する方法を見つけるのにかなり時間がかかりました。

青い背景とTwitterの鳥がアプリのにあるレイヤーであり、鳥が成長するにつれて透明になり、下にアプリが表示されると誤って思い込んでいました。このアプローチは、Twitterの鳥が透明になると、下のアプリではなく青いレイヤーが表示されるため、機能しません。

幸運なことに、読者の皆様は、私が経験したのと同じフラストレーションを経験する必要はありません。この素晴らしいチュートリアルで、良い部分にスキップできます。


正しい方法

コードに移る前に、これをどのように分解するかを理解することが重要です。この効果を視覚化するために、CodePen(数段落下に埋め込み)で再現したので、さまざまなレイヤーをインタラクティブに確認できます。

この効果には、主に3つのレイヤーがあります。1つ目は青い背景レイヤーです。これはアプリの上に表示されているように見えますが、実際には後ろにあります。

次に、プレーンな白いレイヤーがあります。そして最後に、一番前にアプリがあります。


このアニメーションの主な秘訣は、Twitterのロゴをmaskとして使用し、アプリと白いレイヤーの両方をマスクすることです。マスキングの詳細はここでは深く掘り下げませんが、多数の リソースオンラインで入手できます。

このコンテキストでのマスキングの基本は、マスクの不透明なピクセルはマスクしているコンテンツを表示し、マスクの透明なピクセルはマスクしているコンテンツを非表示にする画像を持つことです。

Twitterのロゴをマスクとして使用し、2つのレイヤー(ソリッドホワイトレイヤーとアプリレイヤー)をマスクします。

アプリを表示するには、マスクを画面全体よりも大きくなるまで拡大します。

マスクが拡大されている間、アプリレイヤーの不透明度をフェードインして、アプリを表示し、その背後にあるソリッドホワイトレイヤーを非表示にします。効果を仕上げるために、アプリレイヤーを1より大きいスケールで開始し、アニメーションの終了時に1に縮小します。その後、アプリ以外のレイヤーは二度と表示されないため、非表示にします。

百聞は一見に如かずと言います。インタラクティブな視覚化はどれだけの価値があるのでしょうか?「次のステップ」ボタンをクリックしてアニメーションを進めてください。レイヤーを表示すると、側面図が表示されます。グリッドは、透明なレイヤーを視覚化するのに役立ちます。

それでは、React Nativeについて

さて、何を構築し、アニメーションがどのように機能するかを理解したので、コードに取り組むことができます。これがあなたが本当にここにいる理由です。

このパズルの主要な部分は、React NativeのコアコンポーネントであるMaskedViewIOSです。

import {MaskedViewIOS} from 'react-native';

<MaskedViewIOS maskElement={<Text>Basic Mask</Text>}>
<View style={{backgroundColor: 'blue'}} />
</MaskedViewIOS>;

MaskedViewIOSは、小道具maskElementchildrenを取ります。子はmaskElementによってマスクされます。マスクは画像である必要はなく、任意のビューにすることができます。上記の例の動作は青いビューをレンダリングすることですが、maskElementの「Basic Mask」という単語がある場所でのみ表示されます。複雑な青いテキストを作成しただけです。

私たちがやりたいことは、青いレイヤーをレンダリングし、その上にTwitterのロゴが付いたマスクされたアプリと白いレイヤーをレンダリングすることです。

{
fullScreenBlueLayer;
}
<MaskedViewIOS
style={{flex: 1}}
maskElement={
<View style={styles.centeredFullScreen}>
<Image source={twitterLogo} />
</View>
}>
{fullScreenWhiteLayer}
<View style={{flex: 1}}>
<MyApp />
</View>
</MaskedViewIOS>;

これにより、以下に示すレイヤーが得られます。

それでは、アニメーション化された部分について

このアニメーションを機能させるために必要なすべてのピースが揃ったので、次のステップはそれらをアニメーション化することです。このアニメーションを良い感じにするために、React NativeのAnimated APIを利用します。

Animatedを使用すると、JavaScriptでアニメーションを宣言的に定義できます。デフォルトでは、これらのアニメーションはJavaScriptで実行され、ネイティブレイヤーにフレームごとにどのような変更を加えるかを指示します。JavaScriptはフレームごとにアニメーションを更新しようとしますが、十分な速度で実行できない可能性があり、フレームのドロップ(ジャンク)が発生します。これは私たちが望むものではありません。

Animatedには、このジャンクなしでアニメーションを取得できる特別な動作があります。AnimatedにはuseNativeDriverと呼ばれるフラグがあり、アニメーションの開始時にJavaScriptからネイティブにアニメーション定義を送信することで、ネイティブ側がJavaScriptとフレームごとにやり取りすることなくアニメーションの更新を処理できます。useNativeDriverの欠点は、更新できるプロパティが特定のセットに限定されていることです。主にtransformopacityです。少なくとも今のところ、useNativeDriverで背景色などをアニメーション化することはできません。今後、さらに多くのプロパティを追加していく予定であり、もちろん、プロジェクトに必要なプロパティのPRを送信して、コミュニティ全体に貢献することもできます😀。

このアニメーションをスムーズにしたいので、これらの制約内で作業します。useNativeDriverが内部でどのように機能するかについての詳細は、それを発表したブログ投稿をご覧ください。

アニメーションの分解

アニメーションには4つのコンポーネントがあります

  1. 鳥を拡大して、アプリとソリッドホワイトレイヤーを表示する
  2. アプリをフェードインする
  3. アプリを縮小する
  4. 完了したら、白いレイヤーと青いレイヤーを非表示にする

Animatedでは、アニメーションを定義する主な方法が2つあります。1つ目はAnimated.timingを使用する方法で、アニメーションの実行時間とモーションをスムーズにするためのイージングカーブを正確に指定できます。もう1つのアプローチは、Animated.springなどの物理ベースのAPIを使用することです。Animated.springでは、ばねの摩擦や張力などのパラメータを指定し、物理学によってアニメーションを実行させます。

互いに密接に関連する複数のアニメーションを同時に実行したいと考えています。たとえば、マスクが表示されている間にアプリのフェードインを開始したいと考えています。これらのアニメーションは密接に関連しているため、単一の `Animated.Value` を使用した `Animated.timing` を使用します。

`Animated.Value` は、Animated がアニメーションの状態を知るために使用するネイティブ値のラッパーです。通常、完全なアニメーションにはこのうち1つだけが必要です。Animated を使用するほとんどのコンポーネントは、この値を state に格納します。

このアニメーションは、アニメーション全体を通して異なる時点で発生するステップとして考えているため、`Animated.Value` を 0(0%完了を表す)で開始し、100(100%完了を表す)で終了します。

初期コンポーネントの状態は次のようになります。

state = {
loadingProgress: new Animated.Value(0),
};

アニメーションを開始する準備ができたら、Animated にこの値を 100 にアニメーション化するように指示します。

Animated.timing(this.state.loadingProgress, {
toValue: 100,
duration: 1000,
useNativeDriver: true, // This is important!
}).start();

次に、アニメーションのさまざまな部分と、アニメーション全体のさまざまな段階でそれらが持つべき値の大まかな見積もりを把握しようとします。以下は、アニメーションのさまざまな部分と、時間経過に伴うさまざまなポイントでそれらの値がどうあるべきかを示す表です。

Twitter の鳥のマスクはスケール 1 から始まり、サイズが大きくなる前に小さくなります。そのため、アニメーションの 10% 経過時点で、スケール値は 0.8 になり、最後にスケール 70 まで急上昇します。正直なところ、70 を選択したのはかなり恣意的でしたが、鳥が画面全体を明らかにするのに十分な大きさが必要であり、60 では十分ではありませんでした😀。ただし、この部分で興味深いのは、数値が大きいほど、同じ時間内にそこに到達する必要があるため、成長が速く見えることです。このロゴで見栄えを良くするには、この数値を試行錯誤する必要がありました。ロゴ/デバイスのサイズが異なると、画面全体が表示されるように、この最終スケールを異なる値にする必要があります。

アプリは、少なくとも Twitter ロゴが小さくなるまでは、しばらくの間不透明なままにする必要があります。公式のアニメーションに基づいて、鳥がスケールアップの途中で表示を開始し、非常に迅速に完全に表示したいと考えています。そのため、アニメーション全体の 15% で表示を開始し、30% で完全に表示されます。

アプリのスケールは 1.1 から始まり、アニメーションの終わりまでに通常のスケールに縮小されます。

それでは、コードで見てみましょう。

上記で行ったのは、基本的にアニメーションの進行状況のパーセンテージの値を個々の部分の値にマッピングすることです。Animated では、`.interpolate` を使用してこれを行います。`this.state.loadingProgress` に基づいて補間された値を使用して、アニメーションの各部分に 3 つの異なるスタイルオブジェクトを作成します。

const loadingProgress = this.state.loadingProgress;

const opacityClearToVisible = {
opacity: loadingProgress.interpolate({
inputRange: [0, 15, 30],
outputRange: [0, 0, 1],
extrapolate: 'clamp',
// clamp means when the input is 30-100, output should stay at 1
}),
};

const imageScale = {
transform: [
{
scale: loadingProgress.interpolate({
inputRange: [0, 10, 100],
outputRange: [1, 0.8, 70],
}),
},
],
};

const appScale = {
transform: [
{
scale: loadingProgress.interpolate({
inputRange: [0, 100],
outputRange: [1.1, 1],
}),
},
],
};

これらのスタイルオブジェクトができたので、投稿の前の部分からのビューのスニペットをレンダリングするときに使用できます。`Animated.Value` を使用するスタイルオブジェクトを使用できるのは、`Animated.View`、`Animated.Text`、および `Animated.Image` のみであることに注意してください。

const fullScreenBlueLayer = (
<View style={styles.fullScreenBlueLayer} />
);
const fullScreenWhiteLayer = (
<View style={styles.fullScreenWhiteLayer} />
);

return (
<View style={styles.fullScreen}>
{fullScreenBlueLayer}
<MaskedViewIOS
style={{flex: 1}}
maskElement={
<View style={styles.centeredFullScreen}>
<Animated.Image
style={[styles.maskImageStyle, imageScale]}
source={twitterLogo}
/>
</View>
}>
{fullScreenWhiteLayer}
<Animated.View
style={[opacityClearToVisible, appScale, {flex: 1}]}>
{this.props.children}
</Animated.View>
</MaskedViewIOS>
</View>
);

やったー!これでアニメーションのパーツが思い通りになりました。あとは、二度と見られない青と白のレイヤーをクリーンアップするだけです。

それらをいつクリーンアップできるかを知るには、アニメーションがいつ完了するかを知る必要があります。幸いなことに、`Animated.timing` を呼び出す場所で、`.start` はアニメーションの完了時に実行されるオプションのコールバックを受け取ります。

Animated.timing(this.state.loadingProgress, {
toValue: 100,
duration: 1000,
useNativeDriver: true,
}).start(() => {
this.setState({
animationDone: true,
});
});

アニメーションが完了したかどうかを知るための値が `state` にできたので、青と白のレイヤーを修正してそれを使用できます。

const fullScreenBlueLayer = this.state.animationDone ? null : (
<View style={[styles.fullScreenBlueLayer]} />
);
const fullScreenWhiteLayer = this.state.animationDone ? null : (
<View style={[styles.fullScreenWhiteLayer]} />
);

出来上がり!これでアニメーションが機能し、アニメーションが完了したら未使用のレイヤーがクリーンアップされます。Twitter アプリの読み込みアニメーションを作成しました!

でも、うまくいかない!

心配しないでください、読者の皆様。私も、ガイドがコードの一部だけを提供し、完全なソースを提供しない場合は嫌いです。

このコンポーネントは npm に公開されており、GitHub で react-native-mask-loader として公開されています。スマートフォンで試してみるには、Expo で こちらから入手できます。

その他の資料 / 追加の課題

  1. この gitbook は、React Native のドキュメントを読んだ後、Animated についてさらに学ぶための優れたリソースです。
  2. 実際の Twitter アニメーションでは、マスクの表示が最後の方でスピードアップしているようです。ローダーを変更して、異なるイージング関数(またはスプリング!)を使用して、その動作をより適切に一致させるようにしてください。
  3. マスクの現在の最終スケールはハードコーディングされており、タブレットではアプリ全体が表示されない可能性があります。画面サイズと画像サイズに基づいて最終スケールを計算することは、素晴らしい PR になります。

React Native Monthly #6

2018年1月9日 ·4 分で読めます
Tomislav Tenodi
Speck 創設者

React Native の月例会議は引き続き好調です!次回のセッションについては、この投稿の下部にあるメモを確認してください。

Expo

  • Devin Abbott 氏と Houssein Djirdeh 氏の「Full Stack React Native」書籍のプレリリースおめでとうございます!いくつかの小さなアプリを構築することで、React Native の学習を段階的に進めることができます。書籍を購入する前に、https://www.fullstackreact.com/react-native/ でこれらのアプリを試すことができます。
  • reason-react-native-scripts の最初の(実験的な)バージョンをリリースし、人々が ReasonML を簡単に試せるようにしました。
  • Expo SDK 24 が リリース されました!React Native 0.51 を使用しており、スタンドアロンアプリでの画像のバンドル(初回ロード時にキャッシュする必要なし!)、画像操作 API(トリミング、サイズ変更、回転、反転)、顔検出 API、新しいリリースチャネル機能(特定のチャネルのアクティブリリースの設定とロールバック)、スタンドアロンアプリのビルドを追跡するための Web ダッシュボード、OpenGL Android 実装と Android マルチタスカーに関する長年のバグの修正など、多数の新機能と改善が含まれています。
  • 今年の1月から、React Navigation により多くのリソースを割り当てています。React コンポーネントと Animated や `react-native-gesture-handler` などのプリミティブだけで React Native ナビゲーションを構築することは可能であり、望ましいことであると強く信じており、計画しているいくつかの改善に非常に興奮しています。コミュニティに貢献したい場合は、react-native-mapsreact-native-svg をチェックしてみてください。どちらも助けが必要です!

Infinite Red

Microsoft

  • コア React Native Windows ブリッジを .NET Standard に移行するための プルリクエスト が開始されました。これにより、事実上 OS に依存しなくなります。多くの他の .NET Core プラットフォームが、独自の スレッドモデル、JavaScript ランタイム、および UIManager(JavaScriptCore、Xamarin.Mac、Linux Gtk#、Samsung Tizen オプションなどを考えてみてください)を使用してブリッジを拡張できるようになることが期待されています。

Wix

  • Detox
    • E2E テストでスケールアップするために、CI に費やす時間を最小限に抑えたいと考えており、Detox の並列化サポートに取り組んでいます。
    • E2E でのモッキングをより適切にサポートするために、カスタムフレーバービルドのサポートを有効にするための プルリクエスト を送信しました。
  • DetoxInstruments
    • DetoxInstruments のキラー機能の開発は非常に困難な作業であることが判明しており、いつでも JavaScript バックトレースを取得するには、JS スレッドのサスペンションをサポートするカスタム JSCore 実装が必要です。Wix のアプリでプロファイラーを内部的にテストしたところ、JS スレッドに関する興味深い洞察が明らかになりました。
    • このプロジェクトはまだ一般的に使用できるほど安定していませんが、活発に開発されており、まもなく発表できることを期待しています。
  • React Native Navigation
    • V2 の開発ペースが大幅に加速しました。これまで、1 人の開発者が 20% の時間しか作業していませんでしたが、現在は 3 人の開発者がフルタイムで作業しています!
  • Android のパフォーマンス
    • RN にバンドルされている古い JSCore を最新バージョン(webkitGTK プロジェクトの先端、カスタム JIT 構成を使用)に置き換えたところ、JS スレッドのパフォーマンスが 40% 向上しました。次は、64 ビットバージョンをコンパイルすることです。この取り組みは、Android 用の JSC ビルドスクリプト に基づいています。現在のステータスは こちら で確認できます。

次回のセッション

この会議を、単一の特定のトピック(例:ナビゲーション、React Native モジュールの個別のリポジトリへの移動、ドキュメントなど)について話し合うために再利用することについて議論がありました。そうすることで、React Native コミュニティに最大限貢献できると感じています。次回の会議セッションで行われる可能性があります。トピックとして取り上げてほしい内容があれば、ツイートしてください。

React Native Monthly #5

2017年11月6日 ·4 分で読めます
Tomislav Tenodi
Speck 創設者

React Native の月例会議は続きます!チームの活動状況を見てみましょう。

Callstack

  • React Native CIに取り組んできました。最も重要なのは、TravisからCircleに移行し、React Nativeに単一の統合CIパイプラインを提供したことです。
  • 参加者と一緒にオープンソースプロジェクトに多くのプルリクエストを送信しようと試みたHacktoberfest - React Native editionを開催しました。
  • Haulの開発を続けています。先月は、webpack 3のサポートを含む2つの新しいリリースを行いました。CRNAExpoのサポートを追加し、より良いHMRにも取り組む予定です。ロードマップはイシュートラッカーで公開されています。改善の提案やフィードバックがあれば、お知らせください!

Expo

  • React Native 0.49を使用するExpo SDK 22をリリースし、CRNAを更新しました。
    • 改善されたスプラッシュスクリーンAPI、基本的なARKitサポート、「DeviceMotion」API、iOS11でのSFAuthenticationSessionサポートなどが含まれています。詳細はこちら
  • Snackで複数のJavaScriptファイルを使用できるようになり、画像やその他のアセットをエディターにドラッグアンドドロップするだけでアップロードできるようになりました。
  • iPhone Xのサポートを追加するために、react-navigationに貢献してください。
  • Expoで大規模なアプリケーションを構築する際の課題に焦点を当てています。例えば
    • ステージング、本番、および任意のチャネルへのデプロイのファーストクラスサポート。チャネルは、ロールバックと、特定のチャネルのアクティブリリースの設定をサポートします。早期テスターになりたい場合は、@expo_ioまでお知らせください。
    • スタンドアロンアプリのビルドインフラストラクチャの改善と、スタンドアロンアプリのビルドに画像やその他の非コードアセットをバンドルするサポートの追加にも取り組んでおり、無線でアセットを更新する機能は維持しています。

Facebook

  • RTLサポートの改善
    • 多くのdirection-awareスタイルを導入しています。
      • 位置
        • (left|right) → (start|end)
      • マージン
        • margin(Left|Right) → margin(Start|End)
      • パディング
        • padding(Left|Right) → padding(Start|End)
      • ボーダー
        • borderTop(Left|Right)Radius → borderTop(Start|End)Radius
        • borderBottom(Left|Right)Radius → borderBottom(Start|End)Radius
        • border(Left|Right)Width → border(Start|End)Width
        • border(Left|Right)Color → border(Start|End)Color
    • RTLでは、「left」と「right」の意味が、位置、マージン、パディング、ボーダースタイルで入れ替わっていました。数か月以内に、この動作を削除し、「left」は常に「left」、「right」は常に「right」を意味するようにします。破壊的な変更はフラグの下に隠されています。React Nativeコンポーネントで`I18nManager.swapLeftAndRightInRTL(false)`を使用して、それらを選択してください。
  • 内部ネイティブモジュールのFlowタイピングに取り組んでおり、それらを使用して、ネイティブ実装が実装する必要があるJavaのインターフェースとObjCのプロトコルを生成しています。このコード生成は、早くても来年にはオープンソースになることを願っています。

Infinite Red

  • React Nativeや他のプロジェクトを支援するための新しいOSSツール。詳細はこちら
  • 新しいボイラープレートリリース(コードネーム:Bowser)のためにIgniteを刷新しています

Shoutem

  • Shoutemの開発フローの改善。アプリの作成から最初のカスタム画面までのプロセスを合理化し、非常に簡単にしたいと考えています。そのため、新しいReact Native開発者の障壁を低くしています。新しい機能をテストするためのワークショップをいくつか準備しました。また、新しいフローをサポートするためにShoutem CLIを改善しました。
  • Shoutem UIは、いくつかのコンポーネントの改善とバグ修正を受けました。また、最新のReact Nativeバージョンとの互換性も確認しました。
  • Shoutemプラットフォームは、いくつかの注目すべきアップデートを受けました。新しい統合は、オープンソース拡張プロジェクトの一部として利用可能です。他の開発者からShoutem拡張機能のアクティブな開発が見られることを非常に嬉しく思っています。私たちは積極的に連絡を取り、彼らの拡張機能についてアドバイスとガイダンスを提供しています。

次回のセッション

次回のセッションは、2017年12月6日水曜日に予定されています。会議の成果を改善する方法についてご提案がございましたら、Twitterでご連絡ください。

React Native Monthly #4

·3分間の読書
Mike Grabowski
マイク・グラボウスキー
CallstackのCTO兼共同創設者

React Nativeの月例会議は続きます!各チームからのメモを紹介します。

Callstack

  • React Native EUが終了しました。33カ国から300人以上の参加者がヴロツワフを訪れました。講演はYouTubeでご覧いただけます。
  • カンファレンス後、徐々にオープンソースのスケジュールに戻っています。特筆すべきは、既存の問題のほとんどを修正するreact-native-opentokの次期リリースに取り組んでいることです。

GeekyAnts

React Nativeを採用する開発者の参入障壁を、以下の方法で下げようとしています。

  • React Native EUBuilderX.ioを発表しました。BuilderXは、JavaScriptファイル(現時点ではReact Nativeのみサポート)を直接操作して、美しく、読みやすく、編集可能なコードを生成するデザインツールです。
  • 次のReact Nativeプロジェクトのためのボイラープレートセットを提供するReactNativeSeed.comを立ち上げました。データ型にTypeScriptとFlow、状態管理にMobX、Redux、mobx-state-treeを使用し、CRNAとプレーンなReact-Nativeをスタックとして使用できるなど、さまざまなオプションが用意されています。

Expo

  • まもなくSDK 21をリリースします。これは、react-native 0.48.3のサポートと、ビデオ録画、新しいスプラッシュスクリーンAPI、`react-native-gesture-handler`のサポート、エラー処理の改善など、Expo SDKのバグ修正/信頼性の向上/新機能を追加します。
  • react-native-gesture-handlerに関しては、Software MansionKrzysztof Magiera氏が開発を続けており、私たちはテストと開発時間の一部を資金提供することで彼を支援しています。SDK21でExpoに統合することで、Snackで簡単に試せるようになるので、人々が何を思いつくのか楽しみです。
  • エラーロギング/処理の改善については、ロギングの詳細(特に「問題2」)については内部Expo PRのこのgistを、npm標準ライブラリモジュールのインポートに失敗した試みを処理する変更についてはこのコミットを参照してください。React Nativeのアップストリームでエラーメッセージをこのように改善する機会はたくさんあり、私たちはフォローアップのアップストリームPRに取り組む予定です。コミュニティも参加していただければ幸いです。
  • native.directoryは成長を続けており、GitHubリポジトリからプロジェクトを追加できます。
  • PennAppsHack The NorthHackMIT、そしてまもなくMHacksなど、北米中のハッカソンに参加しています。

Facebook

  • Androidの`<Text>`コンポーネントと`<TextInput>`コンポーネントの改善に取り組んでいます。(`<TextInput>`のネイティブ自動拡張、深くネストされた`<Text>`コンポーネントのレイアウトの問題、より良いコード構造、パフォーマンスの最適化)。
  • 問題やプルリクエストのトリアージを支援してくれる貢献者を募集中です。

Microsoft

  • CodePushのコード署名機能をリリースしました。React Native開発者は、CodePushでアプリケーションバンドルに署名できるようになりました。発表はこちらでご覧いただけます。
  • Mobile CenterへのCodePushの統合の完了に取り組んでいます。テスト/クラッシュの統合も検討しています。

次回のセッション

次回のセッションは、2017年10月10日水曜日に予定されています。これは4回目の会議なので、これらのメモがReact Nativeコミュニティにどのように役立っているかを知りたいと思っています。会議の成果を改善する方法についてご提案がございましたら、Twitterでご連絡ください。

React Native Monthly #3

·5分間の読書
Mike Grabowski
マイク・グラボウスキー
CallstackのCTO兼共同創設者

React Nativeの月例会議は続きます!今月の会議は、ほとんどのチームが出荷で忙しかったため、少し短くなりました。来月は、ポーランドのヴロツワフで開催されるReact Native EUカンファレンスに参加します。チケットを入手して、直接お会いしましょう!その間、私たちのチームが何をしているのか見てみましょう。

チーム

この3回目の会議には、5つのチームが参加しました。

メモ

各チームからのメモを紹介します。

Callstack

  • 最近、`react-native-material-palette`をオープンソース化しました。画像から主要な色を抽出して、視覚的に魅力的なアプリを作成するのに役立ちます。現時点ではAndroidのみですが、将来的にはiOSのサポートを追加することを検討しています。
  • `haul`にHMRサポートといくつかのクールな機能を追加しました!最新のリリースをご覧ください。
  • React Native EU 2017が開催されます!来月はReact Nativeとポーランドが中心です!最後のチケットはこちらから入手できます。

Expo

  • Snack (https://snack.expo.io) で npm パッケージをインストールするためのサポートをリリースしました。Expo の通常の制限が適用されます。パッケージは、Expo に既に含まれていないカスタムネイティブ API に依存することはできません。また、Snack で複数のファイルのサポートとアセットのアップロードに取り組んでいます。SatyajitReact Native Europe で Snack について講演します。
  • カメラ、決済、セキュアストレージ、磁力計、一時停止/再開 fs ダウンロード、改善されたスプラッシュ/ローディング画面を備えた SDK20 をリリースしました。
  • Krzysztofreact-native-gesture-handler の開発を継続しています。ぜひお試しいただき、PanResponder またはネイティブジェスチャ認識を使用して以前に構築したジェスチャを再構築し、発生した問題をお知らせください。
  • JSC デバッグプロトコルの実験、Canny での多くの機能リクエストへの対応に取り組んでいます。

Facebook

  • 先月、GitHub イシュートラッカーの管理について議論し、プロジェクトの保守性を向上させるための改善を試みることを決定しました。
  • 現在、未解決の issue の数は約 600 件で安定しており、しばらくはこの状態が続くと思われます。過去 1 か月間で、アクティビティがない(過去 60 日間にコメントがないと定義)ため、690 件の issue をクローズしました。これらの 690 件のうち、58 件はさまざまな理由(メンテナーが修正を提供することを約束した、または貢献者が issue を開いたままにするための素晴らしい主張をしたなど)で再開されました。
  • 今後とも、古い issue の自動クローズを継続する予定です。トラッカーで開かれたすべての影響力のある issue に対応できる状態になりたいと考えていますが、まだそこには至っていません。特に新しく作成されたプロジェクトに影響を与える、回帰や破壊的変更をもたらす issue を見逃さないように、メンテナーからの協力を得て issue のトリアージを行い、確実に対応する必要があります。協力に関心のある方は、Facebook GitHub Bot を使用して issue とプルリクエストのトリアージを行うことができます。新しいメンテナーガイドには、トリアージと GitHub Bot の使用方法に関する詳細情報が記載されています。issue タスクフォース に参加し、他のアクティブなコミュニティメンバーにも参加を促してください!

Microsoft

  • 新しい Skype アプリは、プラットフォーム間で可能な限り多くのコードを共有できるように、React Native を基盤に構築されています。React Native ベースの Skype アプリは、現在 Android と iOS のアプリストアで入手できます。
  • React Native で Skype アプリを構築する際に、発生したバグや不足している機能に対処するために、React Native にプルリクエストを送信しています。これまでに、約 70 件のプルリクエストがマージ されました。
  • React Native により、Android と iOS の両方の Skype アプリを同じコードベースから開発することができました。また、そのコードベースを使用して Skype Web アプリも開発したいと考えています。その目標を達成するために、React/React Native の上に薄いレイヤーを構築し、ReactXP としてオープンソース化しました。ReactXP は、iOS/Android をターゲットとする場合は React Native に、Web をターゲットとする場合は react-dom にマッピングされる、クロスプラットフォームコンポーネントのセットを提供します。ReactXP の目標は、React Native for Web と呼ばれる別のオープンソースライブラリと似ています。これらのライブラリのアプローチの違いについては、ReactXP FAQ に簡単な説明があります。

Shoutem

  • Shoutem を使用してアプリを構築する際の開発者エクスペリエンスの改善と簡素化に引き続き取り組んでいます。
  • すべてのアプリを react-navigation に移行し始めましたが、より安定したバージョンがリリースされるか、ネイティブナビゲーションソリューションのいずれかが安定するまで、これを延期することにしました。
  • すべての 拡張機能 とほとんどのオープンソースライブラリ(animationthemeui)を React Native 0.47.1 に更新しています。

次回のセッション

次回のセッションは、2017 年 9 月 13 日(水)に予定されています。これは 3 回目の会議なので、これらのメモが React Native コミュニティにどのように役立っているかを知りたいと考えています。会議の成果を改善する方法についてご意見がございましたら、Twitter で ご連絡ください。

マーケットプレイスでのReact Nativeのパフォーマンス

2017年8月7日 ·5分間の読書
Facebook ソフトウェアエンジニア

React Native は、Facebook アプリのトップレベルタブを含む、Facebook ファミリー全体の複数のアプリの複数の場所で利用されています。この記事では、非常に注目度の高い製品である Marketplace に焦点を当てます。これは約 12 か国で利用可能で、ユーザーが他のユーザーによって提供される製品やサービスを発見できるようにします。

2017 年前半には、Relay チーム、Marketplace チーム、モバイル JS プラットフォームチーム、React Native チームの共同作業により、Android Year Class 2010-11 デバイス の Marketplace の Time to Interaction (TTI) を半分に削減しました。Facebook は歴史的にこれらのデバイスをローエンドの Android デバイスと見なしており、どのプラットフォームやデバイスタイプよりも TTI が最も遅くなっています。

典型的な React Native の起動は次のようになります。

免責事項:比率は代表的なものではなく、React Native の構成と使用方法によって異なります。

最初に React Native コア(別名「ブリッジ」)を初期化してから、製品固有の JavaScript を実行します。これは、React Native がネイティブ処理時間でどのネイティブビューをレンダリングするかを決定します。

異なるアプローチ

初期の誤りの 1 つは、Systrace と CTScan にパフォーマンス改善の取り組みを任せすぎたことです。これらのツールは、2016 年に多くの容易に解決できる問題を見つけるのに役立ちましたが、Systrace と CTScan の両方が本番シナリオを代表するものではなく、実際の動作をエミュレートできないことが判明しました。内訳に費やされた時間の比率はしばしば不正確であり、時には大きく外れることもあります。極端な場合、数ミリ秒かかると予想していたものが、実際には数百または数千ミリ秒かかることがあります。とはいえ、CTScan は有用であり、本番環境に到達する前に回帰の 3 分の 1 を捕捉することがわかりました。

Android では、これらのツールの欠点は、1) React Native がマルチスレッドフレームワークであること、2) Marketplace がニュースフィードや他のトップレベルタブなどの多数の複雑なビューと共存していること、3) 計算時間が大きく異なることにあると考えています。そのため、今年後半は、本番環境での測定と内訳が、ほぼすべての意思決定と優先順位付けの指針となりました。

本番環境の計測への道

本番環境の計測は表面上は単純に聞こえますが、実際には非常に複雑なプロセスであることがわかりました。マスターにコミットを反映させるまでの遅延、アプリを Play ストアにプッシュするまでの遅延、作業に自信を持つのに十分な本番サンプルを収集するまでの遅延があるため、それぞれ 2〜3 週間の複数の反復サイクルが必要でした。各反復サイクルでは、内訳が正確かどうか、適切なレベルの粒度を持っているかどうか、期間全体に適切に加算されているかどうかを確認しました。アルファ版とベータ版は一般集団を代表するものではないため、頼ることができませんでした。本質的に、数百万のサンプルの集計に基づいて、非常に正確な本番トレースを非常に手間をかけて構築しました。

内訳の 1 ミリ秒ごとに親メトリクスに適切に加算されていることを綿密に確認した理由の 1 つは、計測にギャップがあることに frühzeitig 気づいたことです。初期の内訳では、スレッドジャンプによって引き起こされるストールが考慮されていませんでした。スレッドジャンプ自体は高価ではありませんが、既に作業を行っているビジー状態のスレッドへのスレッドジャンプは非常に高価です。最終的に、適切なタイミングで `Thread.sleep()` 呼び出しを散りばめることで、これらのブロッキングをローカルで再現し、次の方法で修正することができました。

  1. AsyncTask への依存関係を削除する
  2. UI スレッドでの ReactContext と NativeModules の強制初期化を元に戻す
  3. 初期化時に ReactRootView を測定することへの依存関係を削除する

これらのスレッドブロッキングの問題をまとめて削除することで、起動時間が 25% 以上短縮されました。

本番メトリクスは、以前の仮定のいくつかにも疑問を投げかけました。たとえば、モジュールを 1 つのバンドルに配置することで初期化コストが削減されるとの仮定の下、起動パスで多くの JavaScript モジュールをプリロードしていました。しかし、これらのモジュールをプリロードして共存させるコストは、メリットをはるかに上回っていました。インライン require ブラックリストを再構成し、起動パスから JavaScript モジュールを削除することで、Relay Classic などの不要なモジュール(Relay Modern のみが必要な場合)の読み込みを回避できました。現在、`RUN_JS_BUNDLE` の内訳は 75% 以上高速化されています。

また、製品固有のネイティブモジュールを調査することで、改善点が見つかりました。たとえば、ネイティブモジュールの依存関係を遅延注入することで、そのネイティブモジュールのコストを 98% 削減しました。Marketplace の起動と他の製品との競合をなくすことで、起動時間を同等のインターバルだけ短縮しました。

最も重要なのは、これらの改善点の多くが、React Native で構築されたすべての画面に広く適用できることです。

結論

React Nativeの起動パフォーマンス問題の原因は、JavaScriptの速度が遅いこと、あるいはネットワーク時間が非常に長いことだと考えられています。JavaScript のようなものを高速化すれば、TTI(Time to Interactive)は少なからず短縮されますが、これらは以前考えられていたよりも TTI に占める割合がはるかに小さいことが分かりました。

これまでの教訓は、「**計測、計測、そして計測!**」です。Relay Modern やLazy NativeModulesのように、実行時のコストをビルド時に移行することで、いくつかの改善が見られました。コードの並列化をよりスマートに行ったり、デッドコードを削除することで作業を回避することでも改善が見られました。また、スレッドのブロックを解消するなど、React Native のアーキテクチャを大きく変更することでも改善が見られました。パフォーマンスに万能な解決策はなく、長期的なパフォーマンスの向上は、段階的な計測と改善から得られます。認知バイアスに判断を左右されないでください。代わりに、将来の作業を導くために、本番データを注意深く収集し、解釈してください。

今後の計画

長期的には、Marketplace の TTI をネイティブで構築された同様の製品と同等にし、一般的に React Native のパフォーマンスをネイティブのパフォーマンスと同等にすることを目指しています。さらに、今期はブリッジの起動コストを約 80% 削減しましたが、Prepackなどのプロジェクトや、より多くのビルド時処理によって、React Native ブリッジのコストをゼロに近づける予定です。

React Native Monthly #2

2017年7月28日 ·読了時間:8分
Tomislav Tenodi
Shoutem プロダクトマネージャー

React Native 月例ミーティングが継続中です!今回は、React Native カンファレンス「Chain React」の立役者であるInfinite Redが参加しました。参加者のほとんどが Chain React で講演を行う予定だったため、ミーティングは1週間後に延期されました。カンファレンスの講演はオンラインで公開されているので、ぜひご覧ください。それでは、各チームの活動内容を見ていきましょう。

チーム

第2回目の今回は、9つのチームが参加しました。

メモ

各チームからのメモを紹介します。

Airbnb

Callstack

  • Mike Grabowskiは、いつものように React Native の月次リリースを管理しており、いくつかのベータ版もリリースされました。特に、Windows ユーザーのブロックを解除するため、v0.43.5 ビルドを npm に公開する作業に取り組んでいます。
  • Haulの開発はゆっくりですが、着実に進んでいます。HMR を追加するプルリクエストがあり、その他の改善もリリースされました。最近、業界のリーダー企業がいくつか採用しました。この分野でフルタイムの有給作業を開始する計画があるかもしれません。
  • JestチームのMichał Pierzchałaが今月 Callstack に参加しました。Haulのメンテナンス、そしておそらくMetro BundlerJestの開発にも携わる予定です。
  • Satyajit Sahooがチームに加わりました!
  • OSS 部門からクールなものがたくさん登場予定です。特に、Material Palette API を React Native に導入する作業に取り組んでいます。ネイティブコンポーネントと全く同じルックアンドフィールを提供することを目的としたネイティブ iOS キットを、ついにリリースする予定です。

Expo

  • React Native エコシステムのライブラリの発見と評価を支援するために、Native Directoryを立ち上げました。問題は、ライブラリが多く、テストが難しく、ヒューリスティックを手動で適用する必要があるため、最適なライブラリがすぐにはわからないことです。また、CRNA/Expo と互換性があるかどうかを知るのも困難です。Native Directory はこれらの問題を解決しようとします。ぜひチェックして、あなたのライブラリを追加してください。ライブラリのリストはこちらにあります。これはまだ最初の段階であり、Expo だけではなく、コミュニティによって所有および運営されるようにしたいと考えています。そのため、これが価値があり、より良くしたいと思われる場合は、ご協力ください!
  • Expo SDK 19 を搭載したSnackで npm パッケージをインストールするための初期サポートを追加しました。問題が発生した場合はお知らせください。まだいくつかのバグ修正に取り組んでいます。Native Directory とともに、JS の依存関係のみ、またはExpo SDKに含まれる依存関係を持つライブラリを簡単にテストできるようになるはずです。ぜひお試しください。
  • 多くの改善を加えたExpo SDK19をリリースしました。また、アップデートされた Android JSCを使用するようになりました。
  • Alexander Kotliarskyiと協力して、アプリのユーザーエクスペリエンスを向上させるためのヒントのリストを含むドキュメントを作成しています。ぜひご参加いただき、リストに追加したり、執筆にご協力ください!
  • 引き続き作業中:オーディオ/ビデオ、カメラ、ジェスチャー (Software Mansion と共同で、`react-native-gesture-handler`)、GL カメラの統合。SDK20 (8月) で初めてこれらのいくつかを導入し、それまでに他のものも大幅に改善することを期待しています。バックグラウンド作業 (ジオロケーション、オーディオ、通知の処理など) のためのインフラストラクチャを Expo クライアントに構築し始めたばかりです。
  • Adam Miskiewiczは、react-navigationUINavigationControllerのトランジションを模倣する上で大きな進歩を遂げました。彼のツイートで以前のバージョンをご覧ください。近日中にリリース予定です。また、彼がアップストリームした `MaskedViewIOS` もご覧ください。Android 用の `MaskedView` を実装するスキルと意欲があれば、ぜひご協力ください!

Facebook

  • Facebook は、ネイティブのComponentKitLithoコンポーネントを React Native 内に埋め込むことを社内で検討しています。
  • React Native への貢献は大歓迎です!貢献方法がわからない場合は、「貢献方法」ガイドで開発プロセスと最初のプルリクエストを送信する手順を説明しています。問題のトリアージやドキュメントの更新など、コードを書かずに貢献する方法もあります。
    • この記事の執筆時点で、React Native には635 件未解決の問題249 件未解決のプルリクエストがあります。これはメンテナーにとって負担が大きく、社内で問題が修正された場合、関連するタスクが更新されていることを確認するのが困難です。
    • コミュニティを満足させながら、これを処理するための最良のアプローチが何かわかりません。いくつかの (すべてではありませんが!) オプションには、古い問題をクローズすること、より多くの人に問題を管理する権限を与えること、問題テンプレートに従わない問題を自動的にクローズすることなどがあります。期待値を設定し、予期せぬ事態を避けるために、「メンテナーから期待できること」ガイドを作成しました。メンテナーにとってこのエクスペリエンスをより良くし、問題やプルリクエストを開く人々が意見を聞いてもらえていると感じるようにするためのアイデアがあれば、お知らせください!

GeekyAnts

  • Chain React で、React Native ファイルで動作する Designer Tool のデモを行いました。多くの参加者がウェイティングリストに登録しました.
  • Google Flutter (主要な比較が予定されています)、Kotlin NativeApache Weexなど、他のクロスプラットフォームソリューションも調査し、アーキテクチャの違いと、React Native の全体的なパフォーマンスを向上させるためにそれらから何を学べるかを理解しています。
  • ほとんどのアプリでreact-navigationに切り替え、全体的なパフォーマンスが向上しました。
  • また、NativeBase Market (React Native コンポーネントとアプリのマーケットプレイス、開発者による開発者のための) を発表しました。

Infinite Red

  • Reactotronをご紹介したいと思います。紹介ビデオをご覧ください。近日中に المزيدの機能を追加予定です!
  • Chain React カンファレンスを開催しました。素晴らしいイベントでした。ご参加いただいた皆様、ありがとうございました!ビデオが公開されました!

Microsoft

  • CodePushMobile Centerに統合されました。既存のユーザーのワークフローに変更はありません.
    • アプリの重複に関する問題が報告されています。Mobile Center に既にアプリがある場合です。解決に取り組んでいますが、アプリが2つある場合はお知らせください。マージいたします。
  • Mobile Center は、CodePush のプッシュ通知をサポートするようになりました。また、通知と CodePush の組み合わせをアプリの A/B テストに使用する方法を紹介しました。これは ReactNative アーキテクチャ独自のものです。
  • VS Codeには、ReactNative のデバッグに関する既知の問題があります。数日中にリリースされる拡張機能の次のリリースで、この問題が修正される予定です。
  • Microsoft 社内には React Native に取り組んでいるチームが他にも多数あるため、次回のミーティングでは、すべてのグループからより良い代表者を得られるよう努力します.

Shoutem

  • Shoutemでの React Native 開発を容易にするプロセスを完了しました。Shoutem でアプリを開発する際には、標準の `react-native` コマンドをすべて使用できます。
  • React Native のプロファイリングに最適なアプローチを模索するために、多くの作業を行いました。ドキュメントの大部分は古くなっているため、公式ドキュメントのプルリクエストを作成するか、少なくとも結論をブログ記事にまとめるよう最善を尽くします。
  • ナビゲーションソリューションをreact-navigationに切り替えているため、近日中にフィードバックがあるかもしれません。
  • 生の HTML を React Native コンポーネントツリーに変換する新しい HTML コンポーネントをツールキットでリリースしました。

Wix

  • 私たちは、Metro Bundlerreact-native-repackager の機能を追加するプルリクエストの作業を開始しました。react-native-repackager を更新して、(本番環境で使用している)RN 44 をサポートしました。私たちはこれを detox のモッキングインフラストラクチャに使用しています。
  • 過去3週間、Wixアプリをdetoxテストで網羅的にテストしてきました。これは、この規模のアプリ(エンジニア40人以上)で手動QAを削減する方法を学ぶ素晴らしい経験となりました。その結果、detoxに関するいくつかの問題を解決し、新しいバージョンが公開されました。「フレークゼロポリシー」を遵守しており、テストは今のところ一貫してパスしています。
  • Android版Detoxは順調に進んでいます。コミュニティから多大な支援を受けています。約2週間で初期バージョンがリリースされる予定です。
  • 私たちのパフォーマンステストツールである DetoxInstruments は、当初の想定よりも少し大きくなっています。現在、これをdetoxと密接に結びつかないスタンドアロンツールにする計画を立てています。これにより、一般的なiOSアプリのパフォーマンスを調査できるようになります。また、detoxと統合することで、パフォーマンスメトリクスに関する自動テストを実行できます。

次回のセッション

次回のセッションは2017年8月16日に予定されています。これはまだ2回目の会議なので、これらのメモがReact Nativeコミュニティにどのように役立っているかを知りたいと思っています。会議の成果を改善するための提案があれば、Twitter でお気軽にご連絡ください。

React Native Monthly #1

·読了時間 6分
Tomislav Tenodi
Shoutem プロダクトマネージャー

Shoutem では、React Nativeの初期段階から携わることができて幸運でした。私たちは、初日から素晴らしいコミュニティの一員になりたいと決意しました。すぐに、コミュニティの成長と改善のペースに追いつくことはほとんど不可能であることに気づきました。そのため、主要なReact Nativeコントリビューター全員が、それぞれの取り組みと計画を簡単に発表できる月例会議を開催することにしました。

月例会議

2017年6月14日に、月例会議の最初のセッションを開催しました。React Native Monthlyの使命はシンプルかつ明確です。それは、React Nativeコミュニティの改善です。チームの取り組みを発表することで、オフラインで行われるチーム間の協業が容易になります。

チーム

最初の会議には、8つのチームが参加しました。

今後のセッションには、より多くのコアコントリビューターが参加してくれることを願っています!

メモ

チームの計画は、より幅広い読者にとって興味深いものとなる可能性があるため、React Nativeブログで共有します。では、内容は以下のとおりです。

Airbnb

  • ViewAccessibilityInfo ネイティブモジュールに、A11y(アクセシビリティ)APIを追加する予定です。
  • Androidのネイティブモジュールに、実行スレッドを指定できるAPIを追加することを検討しています。
  • 初期化のパフォーマンス向上について調査してきました。
  • 「アンバンドル」の上に使用する、より高度なバンドル戦略について調査してきました。

Callstack

  • E2Eテストに Detox を使用して、リリースプロセスを改善することを検討しています。プルリクエストは近日中にマージされる予定です。
  • 作業を進めていたBlobのプルリクエストがマージされ、後続のプルリクエストが予定されています。
  • 社内プロジェクト全体で Haul の導入を進め、Metro Bundler とのパフォーマンス比較を行っています。webpackチームと協力して、マルチスレッドパフォーマンスの向上に取り組んでいます。
  • 社内では、オープンソースプロジェクトを管理するためのより良いインフラストラクチャを実装しました。今後数週間で、さらに多くの成果を発表する予定です。
  • React Native Europeカンファレンスが近づいています。まだ目新しいものはありませんが、皆さん招待されています!
  • 代替手段(特にネイティブナビゲーション)を調査するために、react-navigation からしばらくの間、手を引きました。

Expo

  • Snack にnpmモジュールをインストールできるように取り組んでいます。これは、ライブラリがドキュメントに例を追加するのに役立ちます。
  • Krzysztof 氏や Software Mansion の他の人々と協力して、AndroidのJSCアップデートとジェスチャー処理ライブラリに取り組んでいます。
  • Adam Miskiewicz 氏は、react-navigation に焦点を移しています。
  • Create React Native App は、ドキュメントの 入門ガイド に掲載されています。Expoは、ライブラリの作成者に対し、ライブラリがCRNAで動作するかどうかを明確に説明し、動作する場合には設定方法を説明することを推奨しています。

Facebook

  • React Nativeのパッケージャーは、独立したリポジトリである Metro Bundler になりました。ロンドンのMetro Bundlerチームは、コミュニティのニーズに対応し、React Native以外のユースケースに対応するためのモジュール性を向上させ、issueやPRへの対応を迅速化できることに興奮しています。
  • 今後数か月間、React Nativeチームは、プリミティブコンポーネントのAPIの改良に取り組む予定です。レイアウトの癖、アクセシビリティ、Flowタイピングの改善が期待されます。
  • React Nativeチームは、WindowsやmacOSなどのサードパーティ製プラットフォームを完全にサポートするために、リファクタリングを行うことで、今年中にコアモジュール性の向上も計画しています。

GeekyAnts

  • チームは、.js ファイルを直接操作するUI/UXデザインアプリ(コードネーム:Builder)に取り組んでいます。現在、React Nativeのみをサポートしています。Adobe XDやSketchに似ています。
  • チームは、既存のReact Nativeアプリをエディターにロードし、(デザイナーとして視覚的に)変更を加え、変更をJSファイルに直接保存できるようにするために、懸命に取り組んでいます。
  • デザイナーと開発者の間のギャップを埋め、同じリポジトリで作業できるようにしようと努力しています。
  • また、NativeBase は、最近GitHubのスター数が5,000個に達しました。

Microsoft

  • CodePushMobile Center に統合されました。これは、配信、分析、その他のサービスとの統合を強化するための第一歩です。発表はこちらをご覧ください こちら
  • VS Code にデバッグに関するバグがあります。現在修正に取り組んでおり、新しいビルドが提供される予定です。
  • 統合テストに Detox を使用することを検討し、クラッシュレポートと一緒に変数を取得するためにJSCコンテキストを調べています。

Shoutem

  • React Nativeコミュニティのツールを使用して、Shoutemアプリをより簡単に操作できるようにします。Shoutem で作成されたアプリを実行するために、すべてのReact Nativeコマンドを使用できるようになります。
  • React Nativeのプロファイリングツールを調査しています。セットアップに多くの問題が発生したため、その過程で発見した洞察をいくつか書き留める予定です。
  • Shoutemは、React Nativeと既存のネイティブアプリの統合を容易にする取り組みに取り組んでいます。コミュニティからのフィードバックを得るために、社内で開発したコンセプトを文書化する予定です。

Wix

  • Wixアプリの大部分を「手動QAゼロ」に移行するために、Detox を導入する社内作業を行っています。その結果、Detoxは数十人の開発者によって本番環境で本格的に使用されており、急速に成熟しています。
  • ビルド中に任意のファイル拡張子をオーバーライドできるように、Metro Bundler へのサポートを追加する作業を行っています。「ios」や「android」だけでなく、「e2e」や「detox」のようなカスタム拡張子もサポートされます。これをE2Eモッキングに使用することを計画しています。react-native-repackager というライブラリがすでに存在しますが、現在PRを作成中です。
  • パフォーマンステストの自動化について調査しています。これは DetoxInstruments と呼ばれる新しいリポジトリです。オープンソースで開発されているので、ご覧いただけます。
  • KPNのコントリビューターと協力して、Android版Detoxと実機対応に取り組んでいます。
  • シミュレーター/デバイスの自動化を必要とする他のツールを構築できるように、「プラットフォームとしてのDetox」を考えています。例としては、React Native用の Storybook や、Ramの統合テストのアイデアがあります。

次回のセッション

会議は4週間ごと開催されます。次回のセッションは2017年7月12日に予定されています。この会議は始まったばかりなので、これらのメモがReact Nativeコミュニティにどのように役立っているかを知りたいと思っています。今後のセッションで何を扱うべきか、または会議の成果をどのように改善すべきかについて、ご意見がございましたら、Twitter でお気軽にお知らせください。

React Nativeでより良いリストビュー

·読了時間 6分
Spencer Ahrens
Facebook ソフトウェアエンジニア

コミュニティグループでの先行発表 後、多くの方が新しいリストコンポーネントのいくつかを試用し始めましたが、本日正式に発表します。最新のReact Native March 2017リリース候補(0.43-rc.1)では、ListViewDataSource、古い行、無視されたバグ、過剰なメモリ消費はもうありません。ユースケースに最適な新しいコンポーネントスイートから、優れたパフォーマンスと機能セットをすぐに利用できます。

<FlatList>

これは、シンプルで高パフォーマンスなリストのための主力コンポーネントです。データの配列と renderItem 関数を指定するだけで、準備完了です。

<FlatList
data={[{title: 'Title Text', key: 'item1'}, ...]}
renderItem={({item}) => <ListItem title={item.title} />}
/>

<SectionList>

論理セクションに分割されたデータセットをレンダリングする場合、セクションヘッダー(アルファベット順のアドレス帳など)を使用し、場合によっては異種データとレンダリング(ボタンがいくつかあるプロファイルビュー、次にコンポーザー、次に写真グリッド、次にフレンドグリッド、最後にストーリーリストなど)を使用する場合は、これが最適です。

<SectionList
renderItem={({item}) => <ListItem title={item.title} />}
renderSectionHeader={({section}) => <H1 title={section.key} />}
sections={[ // homogeneous rendering between sections
{data: [...], key: ...},
{data: [...], key: ...},
{data: [...], key: ...},
]}
/>

<SectionList
sections={[ // heterogeneous rendering between sections
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
]}
/>

<VirtualizedList>

より柔軟なAPIを備えた舞台裏の実装です。データがプレーン配列ではない場合(たとえば、不変リスト)に特に便利です。

機能

リストは多くのコンテキストで使用されるため、新しいコンポーネントには、ユースケースの大部分をすぐに処理できる機能が満載されています。

  • スクロール読み込み(onEndReached)。
  • プルダウンして更新(onRefresh / refreshing)。
  • 設定可能 な可視性(VPV)コールバック(onViewableItemsChanged / viewabilityConfig)。
  • 横モード(horizontal)。
  • インテリジェントなアイテムとセクションの区切り文字。
  • 複数列のサポート(numColumns
  • scrollToEndscrollToIndex、および scrollToItem
  • より優れたFlowタイピング。

いくつかの注意点

  • コンテンツがレンダーウィンドウからスクロールアウトすると、アイテムサブツリーの内部状態は保持されません。すべてのデータがアイテムデータまたはFlux、Redux、Relayなどの外部ストアにキャプチャされていることを確認してください。

  • これらのコンポーネントは`PureComponent`に基づいています。つまり、`props`が浅い比較で等しい場合、再レンダリングされません。`renderItem`関数が依存するすべてのものが、更新後に`===`ではないpropとして直接渡されるようにしてください。そうでない場合、UIは変更時に更新されない可能性があります。これには、`data` propと親コンポーネントの状態が含まれます。例えば

    <FlatList
    data={this.state.data}
    renderItem={({item}) => (
    <MyItem
    item={item}
    onPress={() =>
    this.setState(oldState => ({
    selected: {
    // New instance breaks `===`
    ...oldState.selected, // copy old data
    [item.key]: !oldState.selected[item.key], // toggle
    },
    }))
    }
    selected={
    !!this.state.selected[item.key] // renderItem depends on state
    }
    />
    )}
    selected={
    // Can be any prop that doesn't collide with existing props
    this.state.selected // A change to selected should re-render FlatList
    }
    />
  • メモリを制限し、スムーズなスクロールを可能にするために、コンテンツは非同期的にオフスクリーンでレンダリングされます。これは、フィルレートよりも速くスクロールし、一時的に空白のコンテンツが表示される可能性があることを意味します。これは、各アプリケーションのニーズに合わせて調整できるトレードオフであり、私たちは舞台裏で改善に取り組んでいます。

  • デフォルトでは、これらの新しいリストは各アイテムの`key` propを探し、それをReactキーとして使用します。代わりに、カスタム`keyExtractor` propを提供することもできます。

パフォーマンス

APIを簡素化するだけでなく、新しいリストコンポーネントはパフォーマンスの大幅な向上も実現しています。主なものは、行数がどれだけ多くても、ほぼ一定のメモリ使用量です。これは、レンダーウィンドウの外側にある要素をコンポーネント階層から完全にアンマウントし、ReactコンポーネントからJSメモリを、シャドウツリーとUIビューからネイティブメモリを再利用することにより、要素を「仮想化」することで実現されます。これには、内部コンポーネントの状態が保持されないという欠点があるため、**重要な状態はコンポーネント自体ではなく、Relay、Redux、Fluxストアなどの外部で追跡するようにしてください。**

レンダーウィンドウを制限することで、Reactとネイティブプラットフォームが行う必要のある作業量(ビューのトラバーサルなど)も削減されます。100万個の要素の最後をレンダリングする場合でも、これらの新しいリストを使用すると、レンダリングするためにすべての要素を反復処理する必要はありません。過剰なレンダリングなしで、`scrollToIndex`を使用して中央にジャンプすることもできます。

スケジューリングについても改善を加え、アプリケーションの応答性を向上させました。レンダーウィンドウの端にあるアイテムは、アクティブなジェスチャ、アニメーション、またはその他のインタラクションが完了した後、低い頻度で、低い優先度でレンダリングされます。

高度な使用方法

`ListView`とは異なり、レンダーウィンドウ内のすべてのアイテムは、propが変更されるたびに再レンダリングされます。ウィンドウイングによってアイテムの数が一定の数に減るため、多くの場合これは問題ありませんが、アイテムが複雑な場合は、パフォーマンスに関するReactのベストプラクティスに従い、コンポーネント内で`React.PureComponent`や`shouldComponentUpdate`を適切に使用して、再帰的なサブツリーの再レンダリングを制限する必要があります。

行の高さをレンダリングせずに計算できる場合は、`getItemLayout` propを提供することでユーザーエクスペリエンスを向上させることができます。これにより、`scrollToIndex`などを使用して特定のアイテムへのスクロールがスムーズになり、コンテンツの高さをレンダリングせずに決定できるため、スクロールインジケーターUIが向上します。

イミュータブルリストなどの代替データ型がある場合は、`<VirtualizedList>`を使用するのが適切です。これは、任意のインデックスのアイテムデータを返すことができる`getItem` propを取り、より緩やかなフロータイピングを備えています。

特殊なユースケースがある場合は、調整できるパラメータも多数あります。たとえば、`windowSize`を使用してメモリ使用量とユーザーエクスペリエンスのバランスを取り、`maxToRenderPerBatch`を使用してフィルレートと応答性を調整し、`onEndReachedThreshold`を使用してスクロール読み込みのタイミングを制御するなど、さまざまなことができます。

今後の作業

  • 既存のサーフェスの移行(最終的には`ListView`の廃止)。
  • 必要に応じてより多くの機能(お知らせください!)。
  • スティッキーセクションヘッダーのサポート。
  • パフォーマンスのさらなる最適化。
  • 状態を持つ関数型アイテムコンポーネントのサポート。

idx: 存在関数

·2 分で読めます
Timothy Yung
Facebookのエンジニアリングマネージャー

Facebookでは、GraphQLでフェッチされたデータ構造内の深くネストされた値にアクセスする必要があることがよくあります。これらの深くネストされた値にアクセスする途中で、1つ以上の中間フィールドがnull許容になるのが一般的です。これらの Null許容の中間フィールドは、プライバシーチェックの失敗から、単にnullが致命的でないエラーを表すための最も柔軟な方法であるという事実まで、さまざまな理由でnullになる可能性があります。

残念ながら、これらの深くネストされた値にアクセスすることは、現在、面倒で冗長です。

props.user &&
props.user.friends &&
props.user.friends[0] &&
props.user.friends[0].friends;

存在演算子を導入するためのECMAScriptの提案があります。これにより、はるかに便利になります。しかし、その提案が確定されるまでは、生活の質を向上させ、既存の言語セマンティクスを維持し、Flowによる型安全性を促進するソリューションが必要です。

私たちは、`idx`と呼ぶ存在*関数*を考案しました。

idx(props, _ => _.user.friends[0].friends);

このコードスニペットの呼び出しは、上記のコードスニペットのブール式と同様に動作しますが、繰り返しが大幅に少なくなります。`idx`関数は、正確に2つの引数を取ります。

  • ネストされた値にアクセスしたい、通常はオブジェクトまたは配列の値。
  • 最初の引数を受け取り、そのネストされた値にアクセスする関数。

理論的には、`idx`関数は、nullまたはundefinedのプロパティにアクセスした結果発生するエラーをtry-catchします。このようなエラーがキャッチされた場合、nullまたはundefinedを返します。(そして、これがidx.jsでどのように実装されるかを確認できます。)

実際には、ネストされたすべてのプロパティアクセスをtry-catchするのは遅く、特定の種類のTypeErrorを区別するのは不安定です。これらの欠点に対処するために、上記の`idx`呼び出しを次の式に変換するBabelプラグインを作成しました。

props.user == null
? props.user
: props.user.friends == null
? props.user.friends
: props.user.friends[0] == null
? props.user.friends[0]
: props.user.friends[0].friends;

最後に、`idx`のカスタムFlow型宣言を追加しました。これにより、2番目の引数のトラバーサルを適切に型チェックしながら、Null許容プロパティへのネストされたアクセスを許可します。

関数、Babelプラグイン、およびFlow宣言は、現在GitHubで入手できます。これらは、**idx**および**babel-plugin-idx** npmパッケージをインストールし、`.babelrc`ファイルのプラグインのリストに「idx」を追加することで使用できます。