Mima Design MemottoWEB DESIGNER · mima

Firebaseを使った簡単なチャットアプリの実装手順

Firebaseを利用すると、サーバーを一から構築しなくても、メッセージの保存やリアルタイム同期を備えたチャットアプリを短時間で作れます。今回は、メールアドレス認証とCloud Firestoreを組み合わせ、投稿者名、本文、送信日時を表示する構成を紹介します。

フロントエンドには、扱いやすいHTML、CSS、JavaScriptを使用します。ReactやVueにも応用できるため、スマートフォンアプリの試作やハッカソンでのプロトタイプ制作にも向いています。まずは最小限の機能に絞り、動作を確認しながら画面や権限を整えていきます。

Firebaseプロジェクトを準備する

Firebaseコンソールで新しいプロジェクトを作成し、ウェブアプリを登録します。表示された設定情報は、JavaScriptからFirebaseへ接続するために必要です。続いてAuthenticationを開き、ログイン方法としてメールアドレスとパスワードを有効にします。

データベースにはCloud Firestoreを選択します。開発中はテストモードで始められますが、公開前には必ずセキュリティルールを変更してください。プロジェクトの作成から各サービスの設定までを記録しておくと、後で環境を作り直すときにも役立ちます。

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  apiKey: "環境変数から読み込む",
  authDomain: "プロジェクトID.firebaseapp.com",
  projectId: "プロジェクトID"
};

const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);

ログインとアカウント状態を実装する

新規登録にはcreateUserWithEmailAndPassword、ログインにはsignInWithEmailAndPasswordを使います。認証処理が成功すると、Firebaseがユーザー固有の識別子を発行します。チャットの投稿者情報には、メールアドレスをそのまま表示せず、ユーザーIDやプロフィール名を利用すると安心です。

画面を開いたときのログイン状態は、onAuthStateChangedで監視できます。未ログインならログインフォームを表示し、認証済みならメッセージ画面へ切り替えます。パスワードの入力ミスや登録済みメールアドレスなど、Firebaseが返すエラーを日本語で伝えると、スマートフォンでも操作しやすくなります。

Firestoreにメッセージを保存する

Firestoreでは、messagesというコレクションを作り、1件の投稿をドキュメントとして保存します。本文、ユーザーID、表示名、作成日時を持たせると、後から投稿者の表示や並び替えがしやすくなります。送信時刻には端末の時計ではなく、serverTimestamp()を使うと時刻のずれを抑えられます。

リアルタイム表示にはonSnapshotを利用します。クエリで作成日時の降順または昇順を指定し、変更が発生するたびに画面を再描画します。投稿後にページを更新しなくても内容が現れるため、チャットらしい操作感を簡単に実現できます。

import {
  addDoc, collection, onSnapshot,
  orderBy, query, serverTimestamp
} from "firebase/firestore";

await addDoc(collection(db, "messages"), {
  text: messageText,
  uid: auth.currentUser.uid,
  name: auth.currentUser.email,
  createdAt: serverTimestamp()
});

const messageQuery = query(
  collection(db, "messages"),
  orderBy("createdAt", "asc")
);

onSnapshot(messageQuery, (snapshot) => {
  const messages = snapshot.docs.map((doc) => ({
    id: doc.id,
    ...doc.data()
  }));
  renderMessages(messages);
});

チャット画面を使いやすく整える

入力欄と送信ボタンは、片手操作を考えて画面下部に固定すると使いやすくなります。本文が空のまま送信されないようにし、長すぎる文字数にも上限を設定します。自分の投稿と相手の投稿で吹き出しの色や位置を変えると、視線の流れも分かりやすくなります。

投稿が追加されたら、メッセージ一覧を最下部へスクロールします。通信中は送信ボタンを一時的に無効化し、連続タップによる二重投稿を防ぎます。画面遷移や表示の動きを工夫したい場合は、スマホアニメーションのコツも、操作感を考える際の参考になります。

セキュリティと公開前の確認

Firestoreのルールでは、ログイン済みユーザーだけがメッセージを読み書きできるように設定します。さらに、作成時のuidがログイン中のユーザーIDと一致するかを検証します。クライアント側で入力制限をしていても、ルール側で確認しなければ不正なリクエストを防げません。

match /messages/{messageId} {
  allow read: if request.auth != null;
  allow create: if request.auth != null
    && request.resource.data.uid == request.auth.uid;
  allow update, delete: if request.auth != null
    && resource.data.uid == request.auth.uid;
}

本番公開前には、スマートフォンの実機でログイン、送信、再読み込み、通信エラーを確認します。利用状況を把握したい場合は、Firebase AnalyticsやGoogle Analyticsを追加し、イベント名を整理しておくと便利です。アクセス解析の記録のように、数値だけでなく利用者の行動を観察する視点も、改善の手がかりになります。

まずは一対一の会話や画像送信を加えず、認証、投稿、リアルタイム更新という基本機能を完成させてみてください。実装した画面や試行錯誤は、制作記録として残しておくと、次のアプリ開発やポートフォリオにも活用できます。