先日リリースしたshallweの技術的な説明です。
以前の記事はこちら
https://crieit.net/posts/shallwe
shallweはフロントエンドに「Vue.js」
バックエンドに「Firebase」を使用しています。
今回は「Buefy」も使いました。BuefyはVue.js用のUIフレームワークで、v-modelなどと組み合わせてリッチな見栄えを簡単に実現できます。Bootstrapみたいなものです。
Buefy: lightweight UI components for Vue.js based on Bulma | Buefy
Vue.jsのSPA(シングル・ページ・アプリケーション)はフロントエンドの高速な開発を可能にします。個人開発では素早く完成してなんぼなので、開発が高速でできるSPAは重宝します。
Firebaseは、ホスティング、データベース、ストレージ、Functions、などがパッケージングされているので、全部詰めで各連携がとても楽です。また、無料枠が設定されているので、流行るかどうかわからないサービスも何も恐れずにリリースできます。
後、個人的に嬉しいのは、グーグルドメインとの連携も簡単な点です。
Vue.jsとFirebaseの組み合わせは、個人開発に非常にマッチしていると考えています。様々な調整が必要な企業のプロジェクトなどは別ですが、技術の選定と把握を全部自分でできる個人開発にはVue.jsとFirebaseはオススメです。この二つを組み合わせると素早く簡単にサービスを作成、リリースすることができます。これから何かウェブサービスを作ろうと考えているプログラミング初心者の方も検討しても良いと思います。
また、今回のアプリでは、リアルタイムチャット機能が必須だったので、FirebaseのFirestoreを使いました。
shallweは、「今日この後」に特化したイベント作成と応募のプラットフォームですが、現在実現している機能はまんまマッチングアプリです。
募集ユーザーは、イベントを作成し、マッチング候補(応募)を待ちます。
イベントの応募ユーザーは、イベントを探し、気に入った募集に申し込みをします。
リクエストを受けた募集ユーザーが、マッチを許可した場合、二人のチャットルームが作成されます。
最後にマッチした二人でチャットルームで待ち合わせの約束をしてもらう。
という流れです。
Firebaseでは、「Hosting」「Firestore」「Cloud storage」「Functions」を使っています。
(当初、SEOとOGP画像のことを考えて、NuxtとGAE(グーグル・アップ・エンジン)の組み合わせも検討しましたが、以前作成したSPAアプリでグーグルサーチコンソールでちゃんとデータが取得されていたこと、OGP対策はfirebase functionsを使えばSPAでも生成できることがわかり、SSR(サーバーサイドレンダリング)のコストの高さからVue.jsとFirebaseを選択しました。SPAのOGP画像については後述します)
shallweで特徴的な機能は、SNSシェア用なOGP画像の機能と、リアルタイムチャット機能です。
めちゃくちゃ便利なSPAですが、唯一ちょっと不便だなと感じるのがこのOGP画像の設定です。ツイッターなどSNSの拡散を意識する場合、キャッチーな画像(OGP画像)を使いたいところです。
よくツイッターで目撃する「質問箱」や「bosyu」というアプリは画像に様々な文字が書かれていて、とても目につきます。
このようなOGP機能をSPAで動的に変更するのは難しく、普通はサーバーサイドでの処理が必要になります。
なぜならSPAは一つのページを動的に変えてコンテンツを作成するため、それぞれのページにあったOGP画像を設定することはできません。このOGP画像の対策のためにサーバーサイドレンダリングが可能であるNuxtを選択する例も見たことがあります。
ただ、この問題を解決する素晴らしい方法があります。Cloud Functionsを使って、SNSのクローラーが判断するページとユーザーがみるページを分けると言う方法です。この三つの記事は大変参考にさせていただきました。
SNS映えするWebアプリを...!FirebaseとVue.jsでSPAのOGP画像の動的生成をやってみたら案外楽だった - Qiita
Vue.jsとFirebaseでOGP画像生成系のサービスを爆速で作ろう - Qiita
Nuxt.js + FirebaseでOGPの仕組みを完全に理解した 〜俳句をSVGで描画するサービスをリリースした話〜 - Qiita
ポイントは3点です。
と言う仕組みです。
この仕組みを使うことでSPAでも動的にシェア画像を作成できます。
shallweでは、募集画面にツイッター用シェアボタンがついており、そこからOGP画像が生成されます。
firebaseの入門者向けサンプルアプリの代名詞とも言えるチャット機能ですが、実際に実用レベルまで高めるのは実は奥深いことがわかりました。
shallweで必要とした大きな機能は
です。
ここまで本格的なチャット機能になるとネットでも情報がないので苦戦しました。
今回は同じような実装をするときに他の人も困るであろう、チャットのメッセージデータの取り扱いについて書いておきます。
LINEをイメージしてもらえるとわかりやすいと思いますが、ユーザーがコメントを送信すると、自分のメッセージと相手のメッセージを判別して時系列で表示します。この機能自体は簡単ですが、問題はデータをどのようにFirestoreに入れるか?です。
私は二つの方法を検討しました。
https://www.katonobo.com/entry/firebase-chat-data
以前の記事にも書きましたが、FirestoreはNoSQLと言うデータベースです。コレクションの中にはドキュメントがあり、そこにデータを格納します。
コレクションは、イメージ的には、病院のカルテがわかりやすいでしょう。病院のカルテだと、クリアファイルに必要な情報がまとめて入っていますよね?そのまとまっているクリアファイルがコレクションで、その中にドキュメントとして各情報が整理されて入っています。
サブコレクションは、クリアファイルの中にさらにクリアファイルを入れておけるといったイメージです。このクリアファイルにはメッセージに関する情報を入れちゃいましょうということです。
この方法はFirebaseの公式ドキュメントでも例として説明されていますし、チャットアプリのメッセージデータの管理としては王道的な方法だと思われます。
Cloud Firestore データモデル | Firebase
また、既読機能について書かれた実践的な記事がありましたがそちらもこの手法です。
ただ、懸念点が一つあります。それは、各メッセージごとにサブコレクションのドキュメントを作っていたら、データの読み込み回数が膨大になるのではないか?ということです。
もしチャットルームでメッセージのやりとりが100回されたら、一つのチャットルームの読み取りだけで100×2で200回です。
Firestoreにはキャッシュ機能がありますが、このような膨大なドキュメントがまたふただび呼び出されるようなことが頻繁にあれば、即座に無料枠はなくなるでしょう。
Firestoreの読み取りは50,000/日は無料なので普通ならよっぽどじゃないとオーバーしないはずですが、このチャット機能の実装は少ないユーザーで簡単に無料枠をオーバーされてしまう可能性があります。
今回は採用したのは、配列を利用する方法です。
チャットルームに、「messages」と言うフィールドを作り、そこに配列として各メッセージを格納していくという方法です。この方法なら、サブコレクションを作成する方法と比べて、メッセージの書き込み回数は変わらないですが、後々の読み込み件数は大きく抑えることができます。
実はFirestoreは以前だと配列の扱いは不便だったのですが、今は配列の検索や追加などが簡単にできるようになってきており、その方法を使えばメッセージを配列の一つとして扱うことも簡単になっています。
https://www.katonobo.com/entry/firestore-array-tip
もちろんこちらの方法ではドキュメントのデータが増えますし、プログラミング的観点で見るとNoSQLのデータの管理の仕方としてはあまり上手くないですが、今回は読み込み件数を抑えるメリットの方を選択しました。
この他にも色々な工夫はありますが、長くなってしまうので省きます。
もしさらに興味がある人はshallweを使って私に会いにきてください。今後、shallweでカフェでのもくもく会(プログラミング勉強会)をしょっちゅう企画していく予定です。
隠すことは何もないので、このアプリを作るに当たって私が得た知見は全部お伝えできます。
もちろん、これからプログラミングを始めたいという初心者の方も大歓迎です!
ということで、shallweを何卒よろしくお願いします!
長文お読みいただきありがとうございました!
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント