はじめに
キッチハイクのエンジニアメンバーでReact Nativeの気になるニュースを持ち寄ってみました!
- はじめに
- React Native Japanコミュニティの活動サマリー
- React Native 0.64 リリース
- React Nativeで機密性の高いユーザーデータを保存するためのアプローチ
- OSSなReact Native アプリ Pix
- JSIを使った高速化の例
- React Native コンポーネントライブラリの紹介
- さいごに
- We're Hiring
React Native Japanコミュニティの活動サマリー
- Meetup #11が3/4に開催されました!
- スライドはこちらから閲覧できます
- 次のMeetup #12 は5月に計画中です
- stand.fmでの放送
- 2/23 #7 キッチハイク社内勉強会 @Discord生配信イベントアフタートーク - React Native Japan | stand.fm
- 3/02 @nabettuさんと話す個人開発について - React Native Japan | stand.fm
- 3/04 @nabettuさんと話す個人開発について〜後半〜 - React Native Japan | stand.fm
- 3/09 いただいたレターへの返信回 その1 - React Native Japan | stand.fm
- 3/12 いただいたレターへの返信回 その2 - React Native Japan | stand.fm
- ハンズオンやります
- 4/04 Day1 環境構築, コンポーネントを作成 connpass 公開中
- 4/18 Day2 Navigation, APIによるデータ取得
- ドキュメントの翻訳プロジェクトもやってます。詳細はReact Native Japanの Discordまで。
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で機密性の高いユーザーデータを保存するためのアプローチ
サンプルコード
ユーザーデータを安全に保存するためのハイブリッドアプローチ
react-native-keychain は、iOSはKeychainを、AndroidはKeystoreを使用する。
- react-native-keychain を使って安全な鍵を作成。これがデータを暗号化するための鍵となる 🔑
- データを、JSON.stringify()などで暗号化しやすい形式に変換
- 生成されたセキュアキーを使用してデータを暗号化🔐。
- 暗号化されたデータを、暗号化されていないストアに書き込み
概要図
類似ライブラリについて
- redux-persist-encrypted-async-storage
- AsyncStorageのシンプルなラッパー。uuidv4を使用しており、記事中で使用している
react-native-securerandom
よりも若干安全性が低い
- AsyncStorageのシンプルなラッパー。uuidv4を使用しており、記事中で使用している
- react-native-secure-storage
- KeyStore/Keychain のサイズ制限がある
- expo-secure-store
- サイズ制限 2048 bytes
コメント
「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. 🚀
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さんの作ったライブラリも使われていますね」
JSIを使った高速化の例
高速な key-valueストレージ react-native-mmkv
- ほぼC++で書かれているため非常に高速
- AsyncStorageと違い、同期通信のみ
- READMEによると、AsyncStorageと比較して約30倍のパフォーマンスが出ている
- 制限事項としてChromeのリモートデバッグは使えないためデバッグの際にはFlipperを使用する必要あり
- 内部でTencentの開発したMMKVを使用している
- MMKVはWeChatの内部で使用されているらしい
コメント
「ストレージは大体の場合OSごとのデフォルトのものを使うことが多いけど、MMKVの場合は速さが求められているってことかな」
「iOS開発だとNSUserDefaultsをよく使うけどそれより高速だとは...」
「JSIを使っていることで、C++を同期的に呼べることも高速化に繋がっているみたい」
「MMKVのほうはWeChatで使われているということで、WeChatのようなメガアプリだと保存するデータ量やデータの数が多そう」
「確かに、一部データを端末に保存するとかはありそうですね」
「AsyncStorageのiOS側の実装を一度見たことがあるのですが、NSUserDefaultsを使わずにファイル書き込みする処理をしていました。AsyncStorageの速さはそもそもどうなんだろう」
React Nativeアプリを50倍速く改善した方法
- 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 で十分。アプリをすばやく構築できることがビジネスをブートストラップするための鍵
コメント
「こちらもJSIを使っていますね!」
「React NativeでJSIを使うための公式の包括的なドキュメントがまだないので手探りで実装したということか...すごい」
「エンコード、デコードの処理を直接C++で書くことで高速になる」
「JSIの使い方を学ぶ際にはめちゃくちゃ勉強になりますね」
「JSIを上手く使えばネイティブアプリより高速に動くアプリが作れるかもしれないというのは夢がありますね!」
「これからもますますJSIの使用例が出てくるでしょうね」
「特定のユースケースにおいてはReact Nativeでパフォーマンスを出すことが厳しい場合はある」
React Native コンポーネントライブラリの紹介
Gifted Chat
- チャット画面を簡単に作成できるライブラリ
- 日本語の記事でも紹介されている
React Native Camera
- ネイティブコードを気にすることなく、いくつかの簡単な機能でデバイスカメラと通信できる
- 写真、ビデオ、顔検出、およびバーコードスキャンをサポートしている
- テキスト認識をサポートし、CocoaPods を介してiOSにインストールできる
コメント
「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
も紹介されていますね」
さいごに
これからも社内で持ち寄った技術ネタを共有します!
We're Hiring
キッチハイクでは、React Native アプリエンジニアを募集中です!