KitchHike Tech Blog

KitchHike Product, Design and Engineering Teams

RN Features 2021年3月号 - React Native 0.64 リリース, JSIを使った高速化の例, React Native コンポーネントライブラリの紹介

はじめに

キッチハイクのエンジニアメンバーでReact Nativeの気になるニュースを持ち寄ってみました!

React Native Japanコミュニティの活動サマリー

React Native 0.64 リリース

  • 主なリリース内容
    • Hermes opt-in on iOS
    • Inline Requires enabled by default
    • Hermes with Proxy Support

Hermes opt-in on iOS

  • Android だけでなく、iOSでも Hermes を有効化できるようになった
  • 低スペックの端末でも動作することが期待できる
  • キッチハイクでも以前 Android で Hermes を有効化しようとした
  • JavaScript エンジンが変わったからか、コードの挙動が変わった部分があった
  • iOS と Android でコード差分が生まれそうだったので断念した
  • iOS でも Hermes が有効化できるようになったので、早速導入できそう

Inline Requires enabled by default

  • Inline Required とは、外部モジュールの実行を起動時ではなく、使用されるタイミングに遅らせることで、起動時間を改善する機能
  • この機能は数年前から推奨されていて、今回デフォルトで有効になるとのこと
  • Babel によって、モジュールのインポートをインラインに変換してくれるみたいなので、開発者は何もしなくてもよい
// before

import { MyFunction } from 'my-module';

const MyComponent = (props) => {
  const result = MyFunction();

  return (<Text>{result}</Text>);
};

// after
const MyComponent = (props) => {
  const result = require('my-module').MyFunction();

  return (<Text>{result}</Text>);
};

Hermes with Proxy Support

  • Proxy を使用しているパッケージが Hermes 下でも動作するようになった
  • よく使用されている react-native-firebase や mobx も Hermes 下で動くようになる
  • キッチハイクでも react-native-firebase を使用しているのでありがたい

コメント

「ついに0.64がリリースされましたね!めでたい!」
「ライブラリ側でProxyを使っているものが今回のリリースで使えるようになるのは大きいですね」
Function.prototype.toString() でソースコード文字列を取得できなくて止まってます」
「hermesはjsのコードを全てbytecodeに変換するので、functionのtoStringが現状できない、ソースコードが変換先に存在しないから(Naturalclarさん)」

React Nativeで機密性の高いユーザーデータを保存するためのアプローチ

medium.com

サンプルコード

github.com

ユーザーデータを安全に保存するためのハイブリッドアプローチ

react-native-keychain は、iOSはKeychainを、AndroidはKeystoreを使用する。

github.com

  • react-native-keychain を使って安全な鍵を作成。これがデータを暗号化するための鍵となる 🔑
  • データを、JSON.stringify()などで暗号化しやすい形式に変換
  • 生成されたセキュアキーを使用してデータを暗号化🔐。
  • 暗号化されたデータを、暗号化されていないストアに書き込み

概要図

f:id:narukami894:20210317192724p:plain https://medium.com/swlh/a-bullet-proof-approach-to-storing-sensitive-user-data-in-react-native-ab3f7a2779f9 より抜粋

類似ライブラリについて

コメント
「iOSのKeychainだと、アプリを消した時にデータが残ってしまう場合があるので要注意です」
「ライブラリを選ぶときに、Keychainなどでデータが残るかどうかと、サイズ制限という2つを観点にしてました」
「サイズ制限がある場合は、仕様調整やデータをサイズ内に調整する工夫をしてます」

OSSなReact Native アプリ Pix

16 x 16 のピクセルアートコミュニティアプリ。React Native 0.63.3. ライブラリの使い方の参考になりそう。

React Navigation, MobX, Firebase, TypeScript, Styled-Components

🎨 Pix is an online pixel art community where everyone can unleash their creativity on a 16x16 canvas, built with React-Native for iOS devices. 🚀

github.com

Stack

  • React Native 0.63.3
  • React Navigation 5.x
  • MobX 6.0.3
  • Firebase 7.x
  • TypeScript 4.1.2
  • Styled-Components 5.2.1

コメント
「モダンなライブラリ構成で参考になりますね!」
Naturalclarさんの作ったライブラリも使われていますね」

github.com

JSIを使った高速化の例

高速な key-valueストレージ react-native-mmkv

github.com

  • ほぼC++で書かれているため非常に高速
  • AsyncStorageと違い、同期通信のみ
  • READMEによると、AsyncStorageと比較して約30倍のパフォーマンスが出ている
  • 制限事項としてChromeのリモートデバッグは使えないためデバッグの際にはFlipperを使用する必要あり
  • 内部でTencentの開発したMMKVを使用している
  • MMKVはWeChatの内部で使用されているらしい

github.com

コメント

「ストレージは大体の場合OSごとのデフォルトのものを使うことが多いけど、MMKVの場合は速さが求められているってことかな」
「iOS開発だとNSUserDefaultsをよく使うけどそれより高速だとは...」
「JSIを使っていることで、C++を同期的に呼べることも高速化に繋がっているみたい」
「MMKVのほうはWeChatで使われているということで、WeChatのようなメガアプリだと保存するデータ量やデータの数が多そう」
「確かに、一部データを端末に保存するとかはありそうですね」
「AsyncStorageのiOS側の実装を一度見たことがあるのですが、NSUserDefaultsを使わずにファイル書き込みする処理をしていました。AsyncStorageの速さはそもそもどうなんだろう」

React Nativeアプリを50倍速く改善した方法

blog.inkdrop.info

  • React Native はNode.js ほど高速ではない
    • またReact Native コミュニティは、Node.js とは異なりバイナリデータ用の堅牢なAPI の提供に重点を置いていない
  • パフォーマンスが必要な場合は、JavaScript ベースのPolyfillを使用しないこと
    • JavaScript ベースのPolyfillによるデータの暗号化・復号化処理が遅すぎるため、アプリで画像が読み込めない問題が起こった
    • そこでバイナリデータの処理をネイティブで実装することにした
  • React Nativeは、NULL文字を含むバイナリ文字列を処理できない
    • 「NULL文字を含むバイナリ文字列が適切に処理されない」問題のため、ネイティブコードを使ってもバイナリデータを扱うことは簡潔ではなかった
  • Polyfillをネイティブモジュールに置き換えた
    • base64 でエンコードされた画像データをJS からReact Native ブリッジを介してWebView に渡すのは冗長で時間がかかる
    • React Native ブリッジを使用せずにファイルシステムからWebView に直接ロードする方法を見つけて、この問題を回避できた
  • C++ でJSI ネイティブモジュールを作成した
    • JSI を使用することにより、JavaScript はC++ ホストオブジェクトへの参照を保持し、それらのメソッドを呼び出すことができる。これにより、先に述べたNULL文字の問題を最終的に回避できた
  • 新しいプロジェクトにReactNativeを採用する必要がありますか?- はい。
    • ほとんどの場合、高品質のアプリを構築するにはRN で十分。アプリをすばやく構築できることがビジネスをブートストラップするための鍵

github.com

github.com

コメント

「こちらもJSIを使っていますね!」
「React NativeでJSIを使うための公式の包括的なドキュメントがまだないので手探りで実装したということか...すごい」
「エンコード、デコードの処理を直接C++で書くことで高速になる」
「JSIの使い方を学ぶ際にはめちゃくちゃ勉強になりますね」
「JSIを上手く使えばネイティブアプリより高速に動くアプリが作れるかもしれないというのは夢がありますね!」
「これからもますますJSIの使用例が出てくるでしょうね」
「特定のユースケースにおいてはReact Nativeでパフォーマンスを出すことが厳しい場合はある」

React Native コンポーネントライブラリの紹介

blog.bitsrc.io

Gifted Chat

  • チャット画面を簡単に作成できるライブラリ

github.com

  • 日本語の記事でも紹介されている

cpoint-lab.co.jp

React Native Camera

  • ネイティブコードを気にすることなく、いくつかの簡単な機能でデバイスカメラと通信できる
  • 写真、ビデオ、顔検出、およびバーコードスキャンをサポートしている
  • テキスト認識をサポートし、CocoaPods を介してiOSにインストールできる

github.com

qiita.com

コメント

「react-native-gifted-chatはReact Native Meetup #11でmeijinさんのLTでも紹介されてましたね」
「チャット画面をまるごと用意できるのはすごい」
react-native-gifted-chat、プロトタイプで一度使ったことがあるのですがすごく便利でした」
react-native-cameraはかなり多機能ですね!」
expo-cameraだとタップしてフォーカスする機能が見つからなく、react-native-cameraに乗り換えてました」
「他には、lottie-react-nativeも紹介されていますね」

speakerdeck.com

さいごに

これからも社内で持ち寄った技術ネタを共有します!

We're Hiring

キッチハイクでは、React Native アプリエンジニアを募集中です!

www.wantedly.com www.wantedly.com www.wantedly.com