Slide 1

Slide 1 text

React Native×Firebase で オンライン指導⽤の チャットアプリを開発している話

Slide 2

Slide 2 text

⽬次 ⾃⼰紹介 開発しているサービス React Native の利⽤ライブラリ React Native の品質管理 React Native の落とし⽳ Firebase の利⽤ライブラリ Firebase の品質管理 Firebase の落とし⽳ この技術選定で良かったと思うこと まとめ

Slide 3

Slide 3 text

⾃⼰紹介 ハンドルネーム” 名⼈” 株式会社NoSchool CTO オンライン家庭教師を広める教育サービス” マナ リンク” を開発しています(https://manalink.jp) 好きな⾔語はTypeScript 好きなIDE はPHPStorm 趣味 将棋( 指すのも観戦するのも好き) ゲーム( 最近はゼルダ無双)

Slide 4

Slide 4 text

開発しているサービス マナリンク 中⾼⽣向けのオンライン家庭教師サービス Web 上で先⽣を探して指導依頼 指導開始後はアプリを使ってご家庭↔ 先⽣でやり 取り

Slide 5

Slide 5 text

図にするとこんな感じ

Slide 6

Slide 6 text

図にするとこんな感じ

Slide 7

Slide 7 text

アプリの開発体制と利⽤技術 開発体制 業務委託エンジニア1 名(+ ときどき CTO) めっちゃベンチャーです 利⽤技術 React Native Expo(Managed Workflow) Firebase TypeScript

Slide 8

Slide 8 text

React Native の利⽤ライブラリ

Slide 9

Slide 9 text

react-native-gifted-chat < > チャット画⾯を丸っと囲う GiftedChat コンポーネントを置くだ け 各メッセージや送信ボタンなどは外 からFunctional なComponent を渡す ことでカスタマイズできる カスタマイズしすぎるとライブラリ の範囲を逸脱してくるので、いつか はリプレイスする

Slide 10

Slide 10 text

チャットをゼロから作るのは割と⼤変 以下の内容は react-native-gifted-chat が やっている チャットの吹き出しの形 よく⾒ると、連投したときの⾓丸の形が微妙に 違う 連投すると最後の投稿だけユーザーアイコンが つく ⽇時表⽰ ⽇付が変わるたびに⽇付表⽰をインサートして いる 表⽰位置 新着メッセージが来るたびに⾃動でスクロール Web ではVue で全部⾃作したけど結構⼤変だった( 勉

Slide 11

Slide 11 text

Firebase×React Hooks 関連のライブラリ react-firebase-hooks https://github.com/CSFrequency/react-firebase-hooks Firestore のCollection データ、読み込み中フラグ、エラー内容をセットで返すHook const const [ [values values, , loading loading, , error error] ] = = useCollectionData useCollectionData< >( (query query, , options options) ); ; react-firebase-pagination-hooks チャットのメッセージをページングして、無限スクロールを実装 loadMore メソッドを実⾏すれば次のデータが読み込める const const [ [messages messages, , { { loaded loaded, , loadingMore loadingMore, , loadMore loadMore } }, , error error] ] = = usePaginationData usePaginationData< >

Slide 12

Slide 12 text

React Native の品質管理 React Native に関してはテストコードは皆無( 汗) 機能が少なく、ライブラリ依存が⼤きいため 毎回ウォークスルーテストを⼿動でしている エラー検知はSentry 画⾯遷移やメッセージ送信時などでイベントを発⽕して記録 エラーログが出ると、イベントを辿ることでユーザーの動きを擬似再現できる ユーザーID も紐付けができる ソースマップをSentry にデプロイすることで、エラーが起きたソースコードの該 当箇所を特定しやすい Sentry Sentry. .addBreadcrumb addBreadcrumb( ({ { category category: : 'ACTION' 'ACTION', , message message: : 'SEND_CHAT_MESSAGE' 'SEND_CHAT_MESSAGE', , data data: : { { roomId roomId: : room room. .id id, ,

Slide 13

Slide 13 text

React Native の落とし⽳ ハマると解決が厳しい 某ライブラリと某ライブラリを併⽤し、かつ特定の動作をユーザーが⾏うとアプリ がクラッシュする事案があった 画⾯が突然ブラックアウトして強制的に再起動になる クラッシュが突然ブラックアウトするためエラーログが取れない ライブラリのソースを追っても、ある程度追うとネイティブのコードになり謎が 深まる 結局何が原因か分からないままに、当該ライブラリの組み合わせを変えることで解消...

Slide 14

Slide 14 text

いつでもiOS/Android で同じと思うなよ現象 チャットで画像を送信するとき、画素数を落とさずにファイルサイズを⼩さくする ために圧縮した expo-image-manipulator のImageManipulator.manipulateAsync で圧縮しようと すると、同じ圧縮率を指定してもAndroid から実⾏すると画像が圧縮されすぎて しまった OS ごとに分岐して圧縮率を調整することで解消 ソースレビューの段階では何ら問題なく⾒えるので恐ろしい 他にも通知周りなど、細かいところで結局OS ごとに分岐する箇所があるので、両 OS での実機確認は必須

Slide 15

Slide 15 text

Firebase の利⽤ライブラリ Cloud Functions 側で使っている技術を軽く紹介していきます

Slide 16

Slide 16 text

firestore-simple Firestore に対する形安全なDAO が⼿に⼊れられるライブラリ const const roomDao roomDao = = firestoreSimple firestoreSimple. .collection collection< >( ({ { path path: : 'rooms' 'rooms' } }) ) const const allRooms allRooms = = await await roomDao roomDao. .fetchAll fetchAll( () ) // allRooms: Room[] // allRooms: Room[]

Slide 17

Slide 17 text

Firebase の設計 Firestore は書き込み処理に重点を置く SQL と違って読み取りクエリが貧弱 ⾮正規化を許容して、読み取りの仕様に合わせて最適化したコレクションを作る 例:チャット部屋⼀覧で最新のメッセージを⾒せるために、messages コレクション のonCreate でrooms コレクションに最新のメッセージを遅れて同期させる 例:全ての未読数の合計を出すために、messages へのonWrite ハンドラでユーザー ごとに未読数を集計して別途保存する

Slide 18

Slide 18 text

Firebase の品質管理 Functions でのエラーログをSlack 通知 https://zenn.dev/meijin/scraps/94d4a70eb77507 Functions でキャッチされなかった例外も含めSlack 等でキャッチアップしたかった Cloud Functions ログ→GCP→ ログルーター→PubSub トピック→Cloud Function→Slack 通知

Slide 19

Slide 19 text

Firebase の落とし⽳ Firebase というかExpo の落とし⽳だが、Expo へのPush 通知は割と⾼頻度( 週に数 回) で502 エラーになる 400 系なら分かるが、502 ならどうしようもない Expo に問い合わせたが、リトライ処理を実装してくださいとのことだったので、 ⾃前で実装しました

Slide 20

Slide 20 text

React Native で良かったと思うこと

Slide 21

Slide 21 text

1. 簡単な修正ならWeb エンジニア( 僕) でも理解・実装できる そもそもReact が個⼈的に好き( 突然の主観) 最近練習を兼ねてRN で個⼈開発しているが、TSX を書くのが楽しいしスタイルも CSS 感覚なので敷居が本当に低い Expo のおかげで環境構築時やコードを書くときに各OS の存在をほとんど意識しな くて良い Firebase JS SDK のコードをNuxt.js とRN でほぼコピペ可能 先⽇Firebase のStorage にファイルを上げる時に、content-disposition ヘッダを指 定することでダウンロード時にファイル名を維持する施策を実装したが、ほぼ同 じコードでWeb/ アプリを実装できたので便利さを実感した

Slide 22

Slide 22 text

2. 受験シーズンに間に合うように開発できた! 昨年6 ⽉から開発スタートし10 ⽉にリリース React Native で開発することで受験シーズンに間に合い、積極的に使ってもらう ことができた ほぼチャット機能のみのシンプルなアプリでも好評だった 親・先⽣・⽣徒がやり取りでき、ファイルや画像も送れるのは当然に⾒えて、案 外事業者側でそこまで内製する企業が少ないらしい 宿題や過去問などファイルをやり取りすることは想像以上に多く、特に先⽣から 好評をいただくことができた 教育事業が最も盛り上がる受験シーズンまでに、最低限どんな機能があればニーズ が満たせるか理解できた スタートアップの検証サイクル的にはとても有り難い技術 ( 初期リリースの内容を予定から絞って、チャットだけを作り込む判断も功を奏し た)

Slide 23

Slide 23 text

まとめ React Native のチャット機能開発 UI はreact-native-gifted-chat が便利 データ読み込みはHooks 関連のライブラリが便利 エラー検知はSentry が便利 Firebase のチャット機能開発 読み取りの都合に合わせて⾮正規化や冗⻑性を許容する Cloud Functions のonWrite 等を使って同期 開発体制を柔軟に決められる技術スタックなので⼤変助かっている

Slide 24

Slide 24 text

告知

Slide 25

Slide 25 text

ご清聴ありがとうございました Twitter: @Meijin_garden