Googleから提供されている、Firebaseでチャットアプリを作成するチュートリアルを試してみたのでメモ。
サンプルファイルの取得
Githubリポジトリからサンプルコードを取得します。
色々ファイルが入っていますが、今回は「web-start」フォルダ内を使用します。
Firebaseプロジェクトの作成
Firebaseのサイトにアクセスして、使ってみるをクリックします。

Googleアカウントにログインしていない場合はログインします。
以下のようなページが表示されるので、プロジェクトを作成をクリックします。

プロジェクト名を追加して、規約の同意にチェックを入れて続行をクリックします。

Google アナリティクスを有効にするかを選択します。
今回は簡単に試したいだけなので、有効にしないで続行をクリックします。

これでプロジェクトの作成が完了しました。

Firebaseプロジェクトの設定
アプリをプロジェクトに追加します。
上部の「>」をクリックします。

アプリのニックネームを入力して、「このアプリのFirebase Hostingも設定します。」にチェックを入れて、アプリを登録をクリックします。

Firebase SDKの追加の指示が表示されますが、今回はチュートリアルのhtmlファイルにすでに記述されていますので飛ばします。

Firebase CLIのインストールとFirebase Hostingへのデプロイは後ほどするので一旦飛ばします。
一通り完了して、コンソール画面に戻りました。
次にGoogleアカウントでアプリにログインできるようにします。
左メニューの開発 > Authentication を選択します。

ログイン方法のタブをクリックします。

プロバイダの一覧からGoogleを選択します。

有効にして、プロジェクトの公開名とサポートメールを設定して保存します。

これでGoogleアカウントでアプリにログインする設定が完了しました。
次にチャットのメッセージを保存するCloud Firestoreを有効にします。
開発 > Database をクリックします。

データベースの作成をクリックします。

セキュリティ保護ルールとロケーションを設定します。
セキュリティは今回動作検証的に使うだけなので「テストモードで開始」を選択、ロケーションは「asia-northeast1」を選択しました。

これでデータベースが作成できました。
この後チュートリアルだと画像の保存用にCloud Storageを有効にしていますが、今回は省略します。

Firebase CLIをインストール
コマンドプロンプトで下記を実行して、Firebase CLIをインストールします。
npm -g install firebase-tools
正しくインストールされたか確認します。
バージョン情報が表示されたらOKです。
firebase --version
次にFirebaseにログインします。
firebase login
エラーレポートの送信を許可するかを聞かれるので、yかnで返答してください。
その後、Firebase CLI がGoogleアカウントへのアクセスをリクエストするので、許可します。

許可すると以下のようなログイン成功画面が表示されます。

これでログイン完了しました。
プロジェクトディレクトリ(web-startのディレクトリ)に移動します。
cd プロジェクトディレクトリ
ローカルのアプリをFirebaseプロジェクトに関連付けします。
firebase use --add
プロジェクトIDとエイリアスを聞かれるので、先ほど作成したプロジェクトのIDを選択して、エイリアスはdefaultにします。
これで一通り準備が完了しましたので、ローカルでアプリを実行してみます。
以下のコマンドを実行します。
firebase serve --only hosting
ブラウザでhttp://localhost:5000を開くと、以下のようにアプリ画面を開くことができました。
この時点ではアプリ用のコードを追加していないので、アプリとしてはまだ機能していません。

Firebaseのインポートと構成
まずFirebase SDKをインポートするのですが、チュートリアルには既に読み込みコードが入っているので飛ばしてOKです。
web-start/public/index.htmlを見ると、下記ファイルの読み込みが入っているかと思います。
<script src="/__/firebase/6.4.0/firebase-app.js"></script> <script src="/__/firebase/6.4.0/firebase-auth.js"></script> <script src="/__/firebase/6.4.0/firebase-storage.js"></script> <script src="/__/firebase/6.4.0/firebase-messaging.js"></script> <script src="/__/firebase/6.4.0/firebase-firestore.js"></script> <script src="/__/firebase/6.4.0/firebase-performance.js"></script> <script src="/__/firebase/init.js"></script>
最後の行のinit.jsはFirebase SDKを設定するファイルになります。
ログインの設定
Googleアカウントでログインできるように設定してみます。
「Sign in with Google」をクリックするとsignIn関数が実行されるようになっているので、この関数の設定を行います。
web-start/public/scripts/main.js 内に空のsignIn関数があるので下記を記述します。
function signIn() {
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider);
}
次にログアウトの設定ですが、「Sign out」をクリックするとsignOut関数が実行されるようになっているので、同様に設定します。
function signOut() {
firebase.auth().signOut();
}
ログイン状態に応じてUIを更新する必要があるので、initFirebaseAuth関数で以下のように設定します。
function initFirebaseAuth() {
firebase.auth().onAuthStateChanged(authStateObserver);
}
ログイン状態が変更する毎に、authStateObserver関数を実行するようにしています。
authStateObserver関数は、main.js内に既に用意されている関数です。
プロフィール画像のURLを取得する関数(getProfilePicUrl)とユーザー名を取得する関数(getUserName)を用意します。
これは上記のauthStateObserver関数内で使用されていて、ログイン時にユーザーの情報を表示するようになります。
function getProfilePicUrl() {
return firebase.auth().currentUser.photoURL || '/images/profile_placeholder.png';
}
function getUserName() {
return firebase.auth().currentUser.displayName;
}
ユーザーがログインしているかを判別する関数(isUserSignedIn)を用意します。
これは未ログイン時にメッセージを送信しようとした際、エラーを表示するために使用されます。
function isUserSignedIn() {
return !!firebase.auth().currentUser;
}
これでログイン周りの実装が完了しましたので、ログインのテストをしてみます。
画面右上の「Sign in with Google」をクリックして、Googleアカウントでログインしてみます。

きちんとログイン情報が表示されればOKです。

メッセージの送信
メッセージを実際に送信して、アプリ上に表示されるようにしてみます。
まずはアプリで送信したメッセージをCloud Firestoreに追加してみます。
SENDをクリックするとsaveMessage関数が実行されるので、以下のように記述します。
function saveMessage(messageText) {
return firebase.firestore().collection('messages').add({
name: getUserName(),
text: messageText,
profilePicUrl: getProfilePicUrl(),
timestamp: firebase.firestore.FieldValue.serverTimestamp()
}).catch(function(error) {
console.error('Error writing new message to database', error);
});
}
これで送信したメッセージがCloud Firestoreに追加されるようになりましたが、まだアプリ上からは確認できません。
送信できているか確認する場合、開発 > Database から確認できます。

送信したメッセージが入っていることが確認できました。
次にメッセージを同期して、アプリ上にも表示されるようにしてみます。
loadMessages関数を以下のように記述します。
function loadMessages() {
// Create the query to load the last 12 messages and listen for new ones.
var query = firebase.firestore()
.collection('messages')
.orderBy('timestamp', 'desc')
.limit(12);
// Start listening to the query.
query.onSnapshot(function(snapshot) {
snapshot.docChanges().forEach(function(change) {
if (change.type === 'removed') {
deleteMessage(change.doc.id);
} else {
var message = change.doc.data();
displayMessage(change.doc.id, message.timestamp, message.name,
message.text, message.profilePicUrl, message.imageUrl);
}
});
});
}
これで同期の設定ができましたので、ブラウザをリロードしてみます。
先ほどテスト送信したメッセージを確認できました。

別のメッセージを送信すると、リアルタイムでアプリに反映されました。

Cloud Firestoreのセキュリティルール
現在データストアへのアクセスを制限しないようになっているので、このルールを変更します。
開発 > Database のルールタブを選択します。

以下のように変更します。
// 変更前
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
// 変更後
service cloud.firestore {
match /databases/{database}/documents {
// Messages:
// - Anyone can read.
// - Authenticated users can add and edit messages.
// - Validation: Check name is same as auth token and text length below 300 char or that imageUrl is a URL.
// - Deletes are not allowed.
match /messages/{messageId} {
allow read;
allow create, update: if request.auth != null
&& request.resource.data.name == request.auth.token.name
&& (request.resource.data.text is string
&& request.resource.data.text.size() <= 300
|| request.resource.data.imageUrl is string
&& request.resource.data.imageUrl.matches('https?://.*'));
allow delete: if false;
}
// FCM Tokens:
// - Anyone can write their token.
// - Reading list of tokens is not allowed.
match /fcmTokens/{token} {
allow read: if false;
allow write;
}
}
}
変更後公開します。

これでCloud Firestoreへのアクセスに制限をかけることができました。
アプリのデプロイ
最後にFirebase CLIを使って、アプリをデプロイします。
firebase.jsonでデプロイするファイルの指定が必要ですが、今回はチュートリアルそのままなので設定不要です。
以下コマンドを実行して、Firebaseプロジェクトにデプロイします。
firebase deploy --except functions
しばらく待って、「Deploy complete」と表示されたらOKです。
https://【プロジェクトID】.web.app のURLでアプリにアクセスできるようになりました。
【参考サイト】
コメントが承認されるまで時間がかかります。