九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、前回「Firebase + Vueでログイン機能をつくる」という記事ではFirebase
を使ったログイン機能をつくってみました。
これは、Authentication
というサービスを使ったものですが、実は他にもサービスがあるので、もう少し深堀りしてみました。
そして、今回紹介する内容は、
Firebaseのデータベース機能「Firestore」
です。
Firestore
は、MySQL
のようなデータ管理をクラウド上で実現するサービスですが、今回はこの機能でリアルタイムなチャットをつくってみたいと思います。
ぜひ皆さんのお役に立てると嬉しいです😊✨
開発環境: Firebase JavaScript SDK 7.12.0
やりたいこと
ログインしてるユーザーだけがチャットに参加できるようにします。
また、メッセージ内容はリアルタイムで更新されるようにします。
では、実際にやっていきましょう❗
前提として
まずFirebase
でログインができることが前提です。
前回記事を参考にしてログインできるユーザーを作成しておいてください。
なお、テストで使うので、ユーザーは2人作っておいてください。
Firebaseの準備
データベースをつくる
では、Firebase
にログインしてデータベースをつくります。
メニューの「Database」をクリックして、「コレクションを開始」をクリックしてください。
コレクションのIDを入力して「次へ」ボタンをクリックします。
(今回はchats
にします)
次にデータベースのフィールドを3つ追加します。
フィールドの中身は以下のとおりです。
- message ・・・ チャットのメッセージ
- created ・・・ 作成日時(タイムスタンプ)
- uid ・・・ 作成したユーザーのID
なお、本来チャットは名前を保存しておくべきですが、複雑になるので今回はuid
だけ保存します。
そして、「保存」をクリックするとデータベースは完了です。
権限を設定する
先ほどデータベースをつくりましたが、実はこのままでは外部からアクセスできません。なぜなら権限が設定されていないからです。
Firestore
では権限は「ルール」で変更します。
画面上部の「ルール」をクリックしてください。
そして、権限の中身を以下のように変更してください。
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /chats/{chatId} { allow read, create: if request.auth.uid != null; } } }
意味としては、「chatsはログインしている人だけ読み書きOK👌」となります。
権限の設定もこれで完了です!
HTMLファイルをつくる
では、ここからは実際にコードを書いていく部分です。
前回と同じくHTMLファイルでOKです。
chat.html
<html> <head> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> </head> <body> <div id="app" class="container pt-5"> <div class="row"> <div class="col-md-4"> <div class="input-group"> <input type="text" class="form-control" v-model="message"> <div class="input-group-append"> <button class="btn btn-primary" @click="addChat">送信</button> </div> </div> <div class="bg-light p-3 my-2" v-if="chat.message" v-for="chat in chats"> <div v-text="chat.message"></div> <small v-text="chat.uid"></small> </div> </div> </div> </div> <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script> <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-auth.js"></script> <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-firestore.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script> new Vue({ el: '#app', data: { message: '', chats: [], db: null }, methods: { getChats() { // チャットデータを取得 ・・・ ④ this.db.collection('chats') .orderBy('created', 'desc') // 最新のものから取得 .limit(25) // 最大25件まで .get() .then(querySnapshot => { let chats = []; querySnapshot.forEach(doc => { const data = doc.data(); chats.push({ uid: data.uid, message: data.message }); }); this.chats = chats; }) .catch(error => { console.log(error); }); }, addChat() { if(this.message === '') { alert('メッセージを入力してください。'); return; } // Firebaseに保存 ・・・ ③ this.db.collection('chats') .add({ message: this.message, uid: firebase.auth().currentUser.uid, // ユーザーID created: firebase.firestore.FieldValue.serverTimestamp() }) .then(docRef => { // const createdId = docRef.id; this.message = ''; }) .catch(error => { console.error('Error adding document: ', error); }); } }, mounted() { // Firebaseの準備 ・・・ ① const firebaseConfig = { apiKey: "**************************", authDomain: "**************************", databaseURL: "**************************", projectId: "**************************", storageBucket: "**************************", messagingSenderId: "**************************", appId: "**************************" }; firebase.initializeApp(firebaseConfig); this.db = firebase.firestore(); // 内容に変更があったら実行される ・・・ ② this.db.collection('chats') .onSnapshot(() => { this.getChats(); }); } }); </script> </body> </html>
では、番号順に説明していきます。
① Firebaseの準備
firebaseConfig
は、前回記事で取得したものを使ってください。
つまり、環境によって中身が違います。
② 内容に変更があったら実行される
onSnapshot()
は、データベースに変更があったら実行されます。
そして、重要なのはこのメソッドは自分以外の人が変更しても起動されるという部分です。
つまり、今回で言うと「自分以外のメッセージが投稿されたタイミングでも、チャット内容が最新のものになる」ということになります。
③ Firebaseに保存
保存するデータは以下のとおりです。
- message ・・・ 入力した内容
- uid ・・・ 現在ログインしている人のuid
- created ・・・ 現在時間
④ チャットデータを取得
投稿されたチャットデータは、「最新のものから最大25件」取得するようにしています。
その後、取得されたデータはchats
に格納されVue
で描画されることになります。
テストしてみる
では、実際にテストしてましょう!
2人のユーザーが必要なのでGoogle Chrome
の通常のタブとプライベート・モードのタブでログインして実行してみます。
では、下側のブラウザから「テスト送信1」と投稿してみましょう。
すると、自動的に両方のブラウザにその内容が表示されました。
では今度は逆に、上のブラウザから「テスト送信2」と送信してみましょう。
すると、今回も両方のブラウザが更新され新しい順に表示されました。
成功です😊✨
おわりに
ということで、今回はFirestore
を使ってリアルタイム・チャットシステムをつくってみました。
なお、今回の開発で少し残念だったのがFirestore
は投稿したユーザーの情報が取得できないということです。(つまり、各データに名前やuid
を登録しておく必要があります)
また、Firestore
のIDは番号ではなくランダムな文字列なため、新着順でデータを取得するには自前で投稿日時を保存しておかないといけない点も少し不便でした。
ただ、今回のコード量でチャット機能を作れるのはとても魅力なので、このあたりの問題点が改善できれば、もっとFirebase
は使いやすいものになると思います😊✨
ぜひ、皆さんも一度試してみてくださいね。
ではでは〜!