見出し画像

FireBase+ReactNative(Expo)でチャットアプリ作りました。

気になるなぁ。
一回触れたいなぁ。
と思いつつ、全く触っていなかったFirebase。
ついに触れ合いました。

Djangoはリアルタイム通信に向いていません。
今までDaphneというライブラリでWebsocketを使っていましたが、プロセスがゾンビ化したり色々面倒なので、リアルタイム性が求められる部分はFirebaseにしようかと思っていました。

最近、僕のサービスClubCloudをスマホアプリ化するということで、バックエンドをフロントエンドと切り離したり、ReactNativeを触り始めたりしました。
で、その延長でFirebaseもちょっと触っちまおうと。

作ったもの

チャット600

こんな感じのちゃっちいチャットアプリです。
gif画質悪くてすみません…。
雰囲気だけ伝われば。

登録、ログイン、リアルタイムチャット、画像の送信ができます。
登録はFirebase Authentication、
データの登録(プッシュ通知トークンとか)はCloud Firestore、
チャットの内容はFirebase Realtime Database、
画像の保存はCloud Storage、
プッシュ通知はCloud Functions
というFirebaseづくし!

ハマったところとか(Expo含む)

1. アプリ内でのfirebaseの初期化
APIキーとかをオブジェクトとして渡して、

firebase.initializeApp(config)

することで、configに全部の情報を入れればRealtimeDBもStorageも全部使えて楽なんですがそういう初期化の仕方なんだ、と最初わからなかったです。
設定のところからFirebase SDK snippetが全部書いてあるページに行けるので、それをコピペすればいいだけで結局は楽チンでした。

2. RealtimeDatabaseのオブジェクトの値を.val()でとるとこ
RealtimeDatabaseで取ってきたオブジェクト、console.logで見ても普通のオブジェクトなんですが、普通に値を取り出そうとするとundefined。
オブジェクト.val()してからじゃないと取り出せないという。

3.データベースに入ってるのが配列ではない
ハマってはないんですが、ちょっとめんどかったので。
例えば、投稿一覧を得るときに、期待するのって、

{ results : [ { 投稿オブジェクト }, { 投稿オブジェクト }... ] }

って配列じゃないですか。
Firebase違うんですよ。
一意に定まるkeyをそれぞれ持っていて、

{  key1 : { 投稿オブジェクト },  key2 : { 投稿オブジェクト } ,...}

って出てくるんですよ。
気持ち悪いけどしゃーないですね。

function snapshotToArray(snapshot){
   let returnArray = [];
   snapshot.forEach(obj=>{
       returnArray.push(obj.val())
   })
   return returnArray
}

こんな感じの、配列に変える関数を用意して使いまわしてました。
これだとkeyは失われますが今回は必要なかったので割愛しました。

4. Storageにて、同名ファイルは上書きされる
AWSのS3だと、同名ファイルには自動でてきとうなサーフィクスつけてくれて名前が被らないように保存できますが、Cloud Storageは違うっぽい。
どうするんだろこれ。
少し調べて放置しました。

5. Storageの保存は単体で、パスが返るだけ
特筆すべきことでもないけど、画像付きのコメントを作りたいとき、まず画像をStorageに送って、その画像の保存先のパスが返ってきたら、コメントをRealtimeDBに、その画像のパスと一緒に保存って感じでした。

6. CloudFunctionのESLint
プッシュ通知のために、for文中でawaitするコードをよく見かけたんですがEslint的にNGということで書き直しました。
あと、firebase init でCloudFunction用のディレクトリ作るときにESLintインストール拒否したらあとあとめんどかった気がするので、最初に言われた通りにインストールするのが吉。

7. 無料ユーザーだといっぺんにPush通知できない(?)
expo.chunkPushNotificationsかexpo.sendPushNotificationsAsyncだったか、まとめてユーザーにプッシュ通知するExpoのAPIなんですが、Firebaseの無料ユーザーだと使えないらしいです(結構使ってる記事多かったんだけどなぁ)。

8. Expoのプッシュ通知のトークンが気持ち悪い
Expoのプッシュ通知のトークン、'ExponentPushToken[xxxxxxxxxxxxxxxx]'って感じなんですよ。
xxxxxxxxxxxxxxxxxxの部分じゃなくて、これ全部をリクエストに入れる必要があるっていう。
Firebase関係ないな。

9. Expoプッシュ通知用のトークンなのでfirebaseのメッセージ用には直接は使えない
さっきのはExpoのプッシュ通知用の話でfirebaseからの直接のプッシュにはもちろん使えない。

10. 結局、プッシュ通知は、fetchを使った

fetch('https://exp.host/--/api/v2/push/send', {
       method: 'POST',
       headers: {
           'Accept': 'application/json',
           'Accept-encoding': 'gzip, deflate',
           'Content-Type': 'application/json',
       },
       body: JSON.stringify(body)
       });

こんな感じでやりました。
これもfirebase関係ないな。
まぁトリガーは、RealtimeDBの更新でCloudFunctionsが起動するって感じだったので。

まとめ

てな感じでした。
記事もドキュメントも充実してたので、1日でだいたいのことがわかりました。
本当にありがたい。
Django+AWSとの併用になるとどうしても情報の所在が二つに分かれてしまいそうで、怖い。
設計ちゃんと考えなくては。
いろんな人にも聞いて。

これからも脱線しない程度に、いろんな技術を試してみて、選択肢を増やしてClubCloudの発展に尽くしていきたいです。

この記事が気に入ったらサポートをしてみませんか?