AngularFire Web コードラボ

1。概要

このコードラボでは、Firebase 製品とサービスを使用してチャット クライアントを実装およびデプロイすることにより、 AngularFireを使用して Web アプリケーションを作成する方法を学習します。

angularfire-2.png

学べること

  • Angular と Firebase を使用して Web アプリを構築します。
  • Cloud Firestore と Cloud Storage for Firebase を使用してデータを同期します。
  • Firebase Authentication を使用してユーザーを認証します。
  • ウェブアプリを Firebase Hosting にデプロイします。
  • Firebase Cloud Messaging を使用して通知を送信します。
  • Web アプリのパフォーマンス データを収集します。

必要なもの

  • WebStormAtomSublime 、またはVS Codeなど、選択した IDE/テキスト エディター
  • パッケージ マネージャーnpm 。通常はNode.jsに付属します。
  • 端末/コンソール
  • Chrome などの任意のブラウザ
  • コードラボのサンプル コード (コードの取得方法については、コードラボの次のステップを参照してください。)

2. サンプルコードを入手する

コマンドラインからコードラボのGitHub リポジトリのクローンを作成します。

git clone https://github.com/firebase/codelab-friendlychat-web

git がインストールされていない場合は、リポジトリを ZIP ファイルとしてダウンロードすることもできます。

スターターアプリをインポートする

IDE を使用して、複製されたリポジトリから 📁 angularfire-startディレクトリを開くかインポートします。この 📁 angularfire-startディレクトリには、完全に機能するチャット Web アプリとなるコードラボの開始コードが含まれています。

3. Firebase プロジェクトを作成して設定する

Firebaseプロジェクトを作成する

  1. Firebaseにサインインします。
  2. Firebase コンソールで[プロジェクトの追加]をクリックし、Firebase プロジェクトにFriendlyChatという名前を付けます。 Firebase プロジェクトのプロジェクト ID を覚えておいてください。
  3. 「このプロジェクトに対して Google アナリティクスを有効にする」のチェックを外します
  4. 「プロジェクトの作成」をクリックします。

構築しようとしているアプリケーションは、ウェブアプリで利用可能な Firebase 製品を使用します。

  • Firebase Authentication を使用すると、ユーザーがアプリに簡単にサインインできるようになります。
  • Cloud Firestore は、構造化データをクラウド上に保存し、データが変更されたときに即座に通知を受け取ります。
  • Cloud Storage for Firebase はファイルをクラウドに保存します。
  • アセットをホストして提供するFirebase Hosting
  • Firebase Cloud Messaging を使用して、プッシュ通知を送信し、ブラウザーのポップアップ通知を表示します。
  • Firebase Performance Monitoring は、アプリのユーザー パフォーマンス データを収集します。

これらの製品の中には、特別な構成が必要な場合や、Firebase コンソールを使用して有効にする必要があるものもあります。

Firebase Web アプリをプロジェクトに追加する

  1. ウェブアイコンをクリックします58d6543a156e56f9.png新しい Firebase ウェブアプリを作成します。
  2. アプリを「Friendly Chat」というニックネームで登録し、 「このアプリの Firebase Hosting も設定します」の横にあるチェックボックスをオンにします。 [アプリの登録]をクリックします。
  3. 次のステップでは、構成オブジェクトが表示されます。 JS オブジェクトのみ (周囲の HTML ではない) をfirebase-config.jsにコピーします。

Web アプリのスクリーンショットを登録する

Firebase Authentication で Google サインインを有効にする

ユーザーが自分の Google アカウントを使用して Web アプリにサインインできるようにするには、 Googleサインイン方法を使用します。

Googleサインインを有効にする必要があります。

  1. Firebase コンソールの左側のパネルで[ビルド]セクションを見つけます。
  2. [認証]をクリックし、 [サインイン方法]タブをクリックします (または、ここをクリックして直接そこに移動します)。
  3. Googleサインイン プロバイダーを有効にして、 [保存]をクリックします。
  4. アプリの公開名を「Friendly Chat」に設定し、ドロップダウン メニューからプロジェクト サポートの電子メールを選択します。
  5. Google Cloud Consoleで OAuth 同意画面を設定し、ロゴを追加します。

d89fb3873b5d36ae.png

Cloud Firestoreを有効にする

このウェブアプリはCloud Firestoreを使用してチャット メッセージを保存し、新しいチャット メッセージを受信します。

Cloud Firestore を有効にする必要があります。

  1. Firebase コンソールの[ビルド]セクションで、 [Firestore データベース]をクリックします。
  2. [Cloud Firestore] ペインで[データベースの作成]をクリックします。

729991a081e7cd5.png

  1. [テスト モードで開始]オプションを選択し、セキュリティ ルールに関する免責事項を読んだ後、 [次へ]をクリックします。

テスト モードでは、開発中にデータベースに自由に書き込むことができます。このコードラボの後半でデータベースの安全性を高めます。

77e4986cbeaf9dee.png

  1. Cloud Firestore データが保存される場所を設定します。これをデフォルトのままにすることも、近くの地域を選択することもできます。 「完了」をクリックして Firestore をプロビジョニングします。

9f2bb0d4e7ca49c7.png

クラウドストレージを有効にする

このウェブアプリは、Cloud Storage for Firebase を使用して写真を保存、アップロード、共有します。

Cloud Storage を有効にする必要があります。

  1. Firebase コンソールの[ビルド]セクションで、 [ストレージ]をクリックします。
  2. [開始する]ボタンがない場合は、クラウド ストレージがすでに有効になっているため、以下の手順に従う必要はありません。
  3. 「開始する」をクリックします。
  4. Firebase プロジェクトのセキュリティ ルールに関する免責事項を読み、 [次へ]をクリックします。

デフォルトのセキュリティ ルールを使用すると、認証されたユーザーはすべて Cloud Storage に何でも書き込むことができます。このコードラボの後半でストレージの安全性を高めます。

62f1afdcd1260127.png

  1. Cloud Storage の場所は、Cloud Firestore データベース用に選択したのと同じリージョンで事前に選択されています。 「完了」をクリックしてセットアップを完了します。

1d7f49ebaddb32fc.png

4. Firebase コマンドライン インターフェイスをインストールする

Firebase コマンドライン インターフェイス (CLI) を使用すると、Firebase Hosting を使用して Web アプリをローカルで提供したり、Web アプリを Firebase プロジェクトにデプロイしたりできます。

  1. 次の npm コマンドを実行して CLI をインストールします。
npm -g install firebase-tools
  1. 次のコマンドを実行して、CLI が正しくインストールされていることを確認します。
firebase --version

Firebase CLI のバージョンが v4.1.0 以降であることを確認してください。

  1. 次のコマンドを実行して、Firebase CLI を承認します。
firebase login

アプリのローカル ディレクトリ (コードラボで前にクローンを作成したリポジトリ) から Firebase Hosting 用のアプリの設定を取得するようにウェブアプリ テンプレートを設定しました。ただし、設定を取得するには、アプリを Firebase プロジェクトに関連付ける必要があります。

  1. コマンドラインがアプリのローカルのangularfire-startディレクトリにアクセスしていることを確認してください。
  2. 次のコマンドを実行して、アプリを Firebase プロジェクトに関連付けます。
firebase use --add
  1. プロンプトが表示されたら、プロジェクト IDを選択し、Firebase プロジェクトにエイリアスを付けます。

エイリアスは、複数の環境 (本番環境、ステージング環境など) がある場合に便利です。ただし、このコードラボでは、 defaultのエイリアスを使用することにします。

  1. コマンドラインの残りの指示に従います。

5.AngularFireをインストールする

プロジェクトを実行する前に、Angular CLI と AngularFire がセットアップされていることを確認してください。

  1. コンソールで次のコマンドを実行します。
npm install -g @angular/cli
  1. 次に、コンソールでangularfire-startディレクトリから次の Angular CLI コマンドを実行します。
ng add @angular/fire

これにより、プロジェクトに必要な依存関係がすべてインストールされます。

  1. プロンプトが表示されたら、Firebase コンソールで設定した機能 ( ng deploy -- hostingAuthenticationFirestoreCloud Functions (callable)Cloud MessagingCloud Storage ) を選択し、コンソールのプロンプトに従います。

6. スターター アプリをローカルで実行する

プロジェクトをインポートして構成したので、Web アプリを初めて実行する準備が整いました。

  1. コンソールで、 angularfire-startディレクトリから次の Firebase CLI コマンドを実行します。
firebase emulators:start
  1. コマンドラインには次の応答が表示されるはずです。
✔  hosting: Local server: http://localhost:5000

Firebase Hostingエミュレータを使用してアプリをローカルで提供しています。 Web アプリはhttp://localhost:5000から利用できるようになります。 srcサブディレクトリの下にあるすべてのファイルが提供されます。

  1. ブラウザを使用して、 http://localhost:5000にあるアプリを開きます。

FriendlyChat アプリの UI が表示されますが、これは (まだ) 機能していません。

angularfire-2.png

アプリは今のところ何もできませんが、あなたの助けがあればすぐにできるようになります。ここまでは UI をレイアウトしただけです。

では、リアルタイム チャットを構築してみましょう。

7. Firebaseをインポートして構成する

Firebaseを構成する

どの Firebase プロジェクトを使用しているかを Firebase SDK に伝えるように構成する必要があります。

  1. Firebase コンソールでプロジェクト設定に移動します。
  2. 「あなたのアプリ」カードで、構成オブジェクトが必要なアプリのニックネームを選択します。
  3. Firebase SDK スニペットペインから「Config」を選択します。

環境ファイル/angularfire-start/src/environments/environment.tsが生成されたことがわかります。

  1. 構成オブジェクトのスニペットをコピーし、それをangularfire-start/src/firebase-config.jsに追加します。

environment.ts

export const environment = {
  firebase: {
    apiKey: "API_KEY",
    authDomain: "PROJECT_ID.firebaseapp.com",
    databaseURL: "https://PROJECT_ID.firebaseio.com",
    projectId: "PROJECT_ID",
    storageBucket: "PROJECT_ID.appspot.com",
    messagingSenderId: "SENDER_ID",
    appId: "APP_ID",
    measurementId: "G-MEASUREMENT_ID",
  },
};

AngularFireをインポートする

コンソールで選択した機能が/angularfire-start/src/app/app.module.tsファイルに自動的にルーティングされたことがわかります。これにより、アプリで Firebase の機能を使用できるようになります。ただし、ローカル環境で開発するには、それらを接続してエミュレータ スイートを使用する必要があります。

  1. /angularfire-start/src/app/app.module.tsimportsセクションを見つけ、提供されている関数を変更して、非運用環境のエミュレータ スイートに接続します。
// ...

import { provideAuth,getAuth, connectAuthEmulator } from '@angular/fire/auth';
import { provideFirestore,getFirestore, connectFirestoreEmulator } from '@angular/fire/firestore';
import { provideFunctions,getFunctions, connectFunctionsEmulator } from '@angular/fire/functions';
import { provideMessaging,getMessaging } from '@angular/fire/messaging';
import { provideStorage,getStorage, connectStorageEmulator } from '@angular/fire/storage';

// ...

provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => {
    const auth = getAuth();
    if (location.hostname === 'localhost') {
        connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
    }
    return auth;
}),
provideFirestore(() => {
    const firestore = getFirestore();
    if (location.hostname === 'localhost') {
        connectFirestoreEmulator(firestore, '127.0.0.1', 8080);
    }
    return firestore;
}),
provideFunctions(() => {
    const functions = getFunctions();
    if (location.hostname === 'localhost') {
        connectFunctionsEmulator(functions, '127.0.0.1', 5001);
    }
    return functions;
}),
provideStorage(() => {
    const storage = getStorage();
    if (location.hostname === 'localhost') {
        connectStorageEmulator(storage, '127.0.0.1', 5001);
    }
    return storage;
}),
provideMessaging(() => {
    return getMessaging();
}),

// ...

app.module.ts

このコードラボでは、Firebase Authentication、Cloud Firestore、Cloud Storage、Cloud Messaging、Performance Monitoring を使用するので、それらのライブラリをすべてインポートします。今後のアプリでは、アプリの読み込み時間を短縮するために、必要な Firebase の部分のみをインポートするようにしてください。

8. ユーザーサインインを設定する

AngularFire はapp.module.tsにインポートされて初期化されているため、使用できるようになります。次に、 Firebase Authenticationを使用してユーザー サインインを実装します。

Google サインインでユーザーを認証する

アプリで、ユーザーが[Google でサインイン]ボタンをクリックすると、 login機能がトリガーされます。 (すでに設定されています。) このコードラボでは、Firebase が ID プロバイダーとして Google を使用することを承認したいと考えています。ポップアップを使用しますが、他にもいくつかの方法が Firebase から利用できます。

  1. angularfire-startディレクトリのサブディレクトリ/src/app/services/で、 chat.service.tsを開きます。
  2. 関数login見つけます。
  3. 関数全体を次のコードに置き換えます。

chat.service.ts

// Signs-in Friendly Chat.
login() {
    signInWithPopup(this.auth, this.provider).then((result) => {
        const credential = GoogleAuthProvider.credentialFromResult(result);
        this.router.navigate(['/', 'chat']);
        return credential;
    })
}

logout機能は、ユーザーが「ログアウト」ボタンをクリックするとトリガーされます。

  1. ファイルsrc/app/services/chat.service.tsに戻ります。
  2. logout関数を見つけます。
  3. 関数全体を次のコードに置き換えます。

chat.service.ts

// Logout of Friendly Chat.
logout() {
    signOut(this.auth).then(() => {
        this.router.navigate(['/', 'login'])
        console.log('signed out');
    }).catch((error) => {
        console.log('sign out error: ' + error);
    })
}

認証状態を追跡する

それに応じて UI を更新するには、ユーザーがログインしているかログアウトしているかを確認する方法が必要です。 Firebase Authentication を使用すると、認証状態が変化するたびにトリガーされるユーザー状態の観察可能データを取得できます。

  1. ファイルsrc/app/services/chat.service.tsに戻ります。
  2. 変数割り当てuser$を見つけます。
  3. 割り当て全体を次のコードに置き換えます。

chat.service.ts

// Observable user
user$ = user(this.auth);

上記のコードは、監視可能なユーザーを返す AngularFire 関数userを呼び出します。これは、認証状態が変化するたび (ユーザーがサインインまたはサインアウトするとき) にトリガーされます。この時点で、UI を更新してリダイレクトしたり、ヘッダー ナビゲーションにユーザーを表示したりすることになります。これらの UI パーツはすべて実装済みです。

アプリへのログインをテストする

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase emulators:startを実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザで開きます。
  2. サインイン ボタンと Google アカウントを使用してアプリにログインします。 auth/operation-not-allowedを示すエラー メッセージが表示された場合は、Firebase コンソールで認証プロバイダとして Google サインインが有効になっていることを確認してください。
  3. ログイン後、プロフィール写真とユーザー名が表示されます。 angularfire-3.png

9. Cloud Firestore にメッセージを書き込む

このセクションでは、アプリの UI にデータを入力できるように、Cloud Firestore にデータを書き込みます。これはFirebase コンソールを使用して手動で実行できますが、基本的な Cloud Firestore の書き込みを示すためにアプリ自体で実行します。

データ・モデル

Cloud Firestore データは、コレクション、ドキュメント、フィールド、サブコレクションに分割されます。チャットの各メッセージを、 messagesという最上位のコレクションにドキュメントとして保存します。

688d7bc5fb662b57.png

Cloud Firestore にメッセージを追加する

ユーザーが書いたチャット メッセージを保存するには、 Cloud Firestoreを使用します。

このセクションでは、ユーザーがデータベースに新しいメッセージを書き込むための機能を追加します。ユーザーが[SEND]ボタンをクリックすると、以下のコード スニペットがトリガーされます。これにより、メッセージ フィールドの内容を含むメッセージ オブジェクトがmessagesコレクション内の Cloud Firestore インスタンスに追加されます。 add()メソッドは、自動生成された ID を持つ新しいドキュメントをコレクションに追加します。

  1. ファイルsrc/app/services/chat.service.tsに戻ります。
  2. 関数addMessage見つけます。
  3. 関数全体を次のコードに置き換えます。

chat.service.ts

// Adds a text or image message to Cloud Firestore.
addMessage = async(textMessage: string | null, imageUrl: string | null): Promise<void | DocumentReference<DocumentData>> => {
    let data: any;
    try {
      this.user$.subscribe(async (user) => 
      { 
        if(textMessage && textMessage.length > 0) {
          data =  await addDoc(collection(this.firestore, 'messages'), {
            name: user?.displayName,
            text: textMessage,
            profilePicUrl: user?.photoURL,
            timestamp: serverTimestamp(),
            uid: user?.uid
          })}
          else if (imageUrl && imageUrl.length > 0) {
            data =  await addDoc(collection(this.firestore, 'messages'), {
              name: user?.displayName,
              imageUrl: imageUrl,
              profilePicUrl: user?.photoURL,
              timestamp: serverTimestamp(),
              uid: user?.uid
            });
          }
          return data;
        }
      );
    }
    catch(error) {
      console.error('Error writing new message to Firebase Database', error);
      return;
    }
}

メッセージ送信のテスト

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase emulators:startを実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザで開きます。
  2. ログイン後、「こんにちは!」などのメッセージを入力し、 「送信」をクリックします。これにより、メッセージが Cloud Firestore に書き込まれます。ただし、データの取得を実装する必要があるため (コードラボの次のセクション) 、実際の Web アプリではデータはまだ表示されません
  3. 新しく追加されたメッセージは Firebase コンソールで確認できます。エミュレータ スイート UI を開きます。 [Build]セクションで[Firestore Database]をクリックします (またはここをクリックすると、新しく追加したメッセージを含むメッセージコレクションが表示されます。

6812efe7da395692.png

10. メッセージを読む

メッセージを同期する

アプリでメッセージを読み取るには、データが変更されたときにトリガーされるオブザーバブルを追加し、新しいメッセージを表示する UI 要素を作成する必要があります。

アプリから新しく追加されたメッセージをリッスンするコードを追加します。このコードでは、 messagesコレクションのスナップショットを取得します。読み込み時に非常に長い履歴が表示されるのを避けるために、チャットの最後の 12 メッセージのみが表示されます。

  1. ファイルsrc/app/services/chat.service.tsに戻ります。
  2. 関数loadMessages見つけます。
  3. 関数全体を次のコードに置き換えます。

chat.service.ts

// Loads chat message history and listens for upcoming ones.
loadMessages = () => {
  // Create the query to load the last 12 messages and listen for new ones.
  const recentMessagesQuery = query(collection(this.firestore, 'messages'), orderBy('timestamp', 'desc'), limit(12));
  // Start listening to the query.
  return collectionData(recentMessagesQuery);
}

データベース内のメッセージをリッスンするには、 collection関数を使用してコレクションに対するクエリを作成し、リッスンするデータがどのコレクションに含まれているかを指定します。上記のコードでは、 messages内の変更をリッスンしています。コレクション。チャット メッセージが保存される場所です。また、limit limit(12)を使用して最後の 12 個のメッセージのみをリッスンし、 orderBy('timestamp', 'desc')を使用してメッセージを日付順に並べ替えて、最新の 12 個のメッセージを取得することで、制限を適用しています。

collectionData関数は内部でスナップショットを使用します。コールバック関数は、クエリに一致するドキュメントに変更があったときにトリガーされます。これは、メッセージが削除、変更、または追加された場合に発生する可能性があります。これについて詳しくは、 Cloud Firestore のドキュメントをご覧ください。

メッセージの同期をテストする

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase emulators:startを実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザで開きます。
  2. データベース内に以前に作成したメッセージが FriendlyChat UI に表示されるはずです (以下を参照)。気軽に新しいメッセージを書いてください。それらは即座に表示されるはずです。
  3. (オプション)エミュレータ スイートのFirestoreセクションで直接、手動でメッセージを削除、変更、または新しいメッセージを追加してみることができます。変更は UI に反映される必要があります。

おめでとう!アプリで Cloud Firestore ドキュメントを読んでいます。

angularfire-2.png

11. 画像を送信する

次に、画像を共有する機能を追加します。

Cloud Firestore は構造化データの保存に適していますが、Cloud Storage はファイルの保存に適しています。 Cloud Storage for Firebase はファイル/BLOB ストレージ サービスであり、ユーザーがアプリを使用して共有する画像を保存するために使用します。

画像をクラウドストレージに保存する

このコードラボでは、ファイル ピッカー ダイアログをトリガーするボタンがすでに追加されています。ファイルを選択すると、 saveImageMessage関数が呼び出され、選択したファイルへの参照を取得できます。 saveImageMessage関数は次のことを実行します。

  1. チャット フィードに「プレースホルダー」チャット メッセージを作成し、画像のアップロード中にユーザーに「読み込み中」アニメーションが表示されるようにします。
  2. 画像ファイルを Cloud Storage のパス/<uid>/<file_name>にアップロードします。
  3. 画像ファイルの一般に読み取り可能な URL を生成します。
  4. 一時的な読み込み画像の代わりに、新しくアップロードされた画像ファイルの URL を使用してチャット メッセージを更新します。

次に、画像を送信する機能を追加します。

  1. ファイルsrc/chat.service.tsに戻ります。
  2. 関数saveImageMessageを見つけます。
  3. 関数全体を次のコードに置き換えます。

チャット.サービス.ts

// Saves a new message containing an image in Firebase.
// This first saves the image in Firebase storage.
saveImageMessage = async(file: any) => {
  try {
    // 1 - You add a message with a loading icon that will get updated with the shared image.
    const messageRef = await this.addMessage(null, this.LOADING_IMAGE_URL);

    // 2 - Upload the image to Cloud Storage.
    const filePath = `${this.auth.currentUser?.uid}/${file.name}`;
    const newImageRef = ref(this.storage, filePath);
    const fileSnapshot = await uploadBytesResumable(newImageRef, file);
    
    // 3 - Generate a public URL for the file.
    const publicImageUrl = await getDownloadURL(newImageRef);

    // 4 - Update the chat message placeholder with the image's URL.
    messageRef ?
    await updateDoc(messageRef,{
      imageUrl: publicImageUrl,
      storageUri: fileSnapshot.metadata.fullPath
    }): null;
  } catch (error) {
    console.error('There was an error uploading a file to Cloud Storage:', error);
  }
}

画像の送信テスト

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase emulators:startを実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザで開きます。
  2. ログイン後、左下の画像アップロードボタンをクリックしてくださいangularfire-4.pngファイルピッカーを使用して画像ファイルを選択します。画像をお探しの場合は、この素敵なコーヒー カップの画像をご自由にお使いください。
  3. 選択した画像を含む新しいメッセージがアプリの UI に表示されます。 angularfire-2.png

サインインしていないときに画像を追加しようとすると、画像を追加するにはサインインする必要があることを示すエラーが表示されます。

12. 通知を表示する

次に、ブラウザ通知のサポートを追加します。新しいメッセージがチャットに投稿されると、アプリはユーザーに通知します。 Firebase Cloud Messaging (FCM) は、メッセージと通知を無料で確実に配信できるクロスプラットフォームのメッセージング ソリューションです。

FCM サービス ワーカーを追加する

Web アプリには、Web 通知を受信して​​表示するService Worker が必要です。

メッセージング プロバイダーは、AngularFire が追加されたときにすでにセットアップされているはずです。/angularfire-start/src/app/app.module.ts の imports セクションに次のコードが存在することを確認してください/angularfire-start/src/app/app.module.ts

provideMessaging(() => {
    return getMessaging();
}),

app/app.module.ts

Service Worker は、通知の表示を処理する Firebase Cloud Messaging SDK をロードして初期化するだけで済みます。

FCM デバイス トークンを取得する

デバイスまたはブラウザで通知が有効になっている場合、デバイス トークンが与えられます。このデバイス トークンは、特定のデバイスまたは特定のブラウザに通知を送信するために使用します。

ユーザーがサインインするときに、 saveMessagingDeviceToken関数を呼び出します。ここで、ブラウザからFCM デバイス トークンを取得し、Cloud Firestore に保存します。

chat.service.ts

  1. 関数saveMessagingDeviceTokenを見つけます。
  2. 関数全体を次のコードに置き換えます。

chat.service.ts

// Saves the messaging device token to Cloud Firestore.
saveMessagingDeviceToken= async () => {
    try {
      const currentToken = await getToken(this.messaging);
      if (currentToken) {
        console.log('Got FCM device token:', currentToken);
        // Saving the Device Token to Cloud Firestore.
        const tokenRef = doc(this.firestore, 'fcmTokens', currentToken);
        await setDoc(tokenRef, { uid: this.auth.currentUser?.uid });
 
        // This will fire when a message is received while the app is in the foreground.
        // When the app is in the background, firebase-messaging-sw.js will receive the message instead.
        onMessage(this.messaging, (message) => {
          console.log(
            'New foreground notification from Firebase Messaging!',
            message.notification
          );
        });
      } else {
        // Need to request permissions to show notifications.
        this.requestNotificationsPermissions();
      }
    } catch(error) {
      console.error('Unable to get messaging token.', error);
    };
}

ただし、このコードは最初は機能しません。アプリがデバイス トークンを取得できるようにするには、ユーザーがアプリに通知を表示する権限を付与する必要があります (コードラボの次のステップ)。

通知を表示する権限をリクエストする

ユーザーがアプリに通知を表示する権限をまだ付与していない場合、デバイス トークンは与えられません。この場合、 requestPermission()メソッドを呼び出すと、この許可を求めるブラウザ ダイアログが表示されます (サポートされているブラウザの場合)。

8b9d0c66dc36153d.png

  1. ファイルsrc/app/services/chat.service.tsに戻ります。
  2. requestNotificationsPermissions関数を見つけます。
  3. 関数全体を次のコードに置き換えます。

chat.service.ts

// Requests permissions to show notifications.
requestNotificationsPermissions = async () => {
    console.log('Requesting notifications permission...');
    const permission = await Notification.requestPermission();
    
    if (permission === 'granted') {
      console.log('Notification permission granted.');
      // Notification permission granted.
      await this.saveMessagingDeviceToken();
    } else {
      console.log('Unable to get permission to notify.');
    }
}

デバイストークンを取得する

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase emulators:startを実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザで開きます。
  2. ログイン後、通知許可ダイアログが表示されます。 bd3454e6dbfb6723.png
  3. 「許可」をクリックします。
  4. ブラウザの JavaScript コンソールを開きます。次のメッセージが表示されます: Got FCM device token: cWL6w:APA91bHP...4jDPL_A-wPP06GJp1OuekTaTZI5K2Tu
  5. デバイストークンをコピーします。コードラボの次の段階で必要になります。

デバイスに通知を送信する

デバイス トークンを取得したので、通知を送信できます。

  1. Firebase コンソールの [クラウド メッセージング] タブを開きます。
  2. 「新規通知」をクリックします
  3. 通知のタイトルと通知テキストを入力します。
  4. 画面右側の「テストメッセージを送信」をクリックします。
  5. ブラウザの JavaScript コンソールからコピーしたデバイス トークンを入力し、プラス (「+」) 記号をクリックします。
  6. 「テスト」をクリックします

アプリがフォアグラウンドにある場合は、JavaScript コンソールに通知が表示されます。

アプリがバックグラウンドにある場合は、次の例のようにブラウザに通知が表示されます。

de79e8638a45864c.png

13. Cloud Firestore セキュリティ ルール

データベースのセキュリティ ルールを表示する

Cloud Firestore は、特定のルール言語を使用して、アクセス権、セキュリティ、データ検証を定義します。

このコードラボの初めに Firebase プロジェクトを設定するときに、データストアへのアクセスを制限しないように、「テスト モード」のデフォルトのセキュリティ ルールを使用することを選択しました。 Firebase コンソールの [データベース]セクションの[ルール]タブで、これらのルールを表示および変更できます。

現時点では、データストアへのアクセスを制限しないデフォルトのルールが表示されているはずです。これは、どのユーザーもデータストア内のコレクションに対して読み取りと書き込みができることを意味します。

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}

次のルールを使用してルールを更新し、内容を制限します。

firestore.rules

rules_version = '2';

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 Storage のセキュリティ ルールを表示する

Cloud Storage for Firebase は、特定のルール言語を使用してアクセス権、セキュリティ、データ検証を定義します。

このコードラボの開始時に Firebase プロジェクトを設定するときに、認証されたユーザーのみに Cloud Storage の使用を許可するデフォルトの Cloud Storage セキュリティ ルールを使用することを選択しました。 Firebase コンソール[ストレージ]セクションの[ルール]タブで、ルールを表示および変更できます。サインインしているユーザーにストレージ バケット内のファイルの読み取りと書き込みを許可するデフォルトのルールが表示されます。

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

次のことを行うためにルールを更新します。

  • 各ユーザーが自分の特定のフォルダーにのみ書き込みできるようにする
  • 誰でも Cloud Storage から読み取りできるようにする
  • アップロードされるファイルが画像であることを確認してください
  • アップロードできる画像のサイズを最大 5 MB に制限する

これは、次のルールを使用して実装できます。

ストレージルール

rules_version = '2';

// Returns true if the uploaded file is an image and its size is below the given number of MB.
function isImageBelowMaxSize(maxSizeMB) {
  return request.resource.size < maxSizeMB * 1024 * 1024
      && request.resource.contentType.matches('image/.*');
}

service firebase.storage {
  match /b/{bucket}/o {
    match /{userId}/{messageId}/{fileName} {
      allow write: if request.auth != null && request.auth.uid == userId && isImageBelowMaxSize(5);
      allow read;
    }
  }
}

14. Firebase Hosting を使用してアプリをデプロイする

Firebase は、アセットや Web アプリを提供するためのホスティング サービスを提供します。 Firebase CLI を使用してファイルを Firebase Hosting にデプロイできます。デプロイする前に、どのローカル ファイルをデプロイする必要があるかをfirebase.jsonファイルで指定する必要があります。このコードラボでは、このコードラボ中にファイルを提供するためにこの手順が必要だったので、これはすでに実行されています。ホスティング設定は、 hosting属性で指定します。

ファイアベース.json

{
  // If you went through the "Cloud Firestore Security Rules" step.
  "firestore": {
    "rules": "firestore.rules"
  },
  // If you went through the "Storage Security Rules" step.
  "storage": {
    "rules": "storage.rules"
  },
  "hosting": {
    "public": "./public"
  }
}

これらの設定は、すべてのファイルを./publicディレクトリにデプロイすることを CLI に指示します ( "public": "./public" )。

  1. コマンドラインがアプリのローカルのangularfire-startディレクトリにアクセスしていることを確認してください。
  2. 次のコマンドを実行して、ファイルを Firebase プロジェクトにデプロイします。
ng deploy

次に、Firebase オプションを選択し、コマンド ラインのプロンプトに従います。

  1. コンソールには以下が表示されるはずです。
=== Deploying to 'friendlychat-1234'...

i  deploying firestore, storage, hosting
i  storage: checking storage.rules for compilation errors...
✔  storage: rules file storage.rules compiled successfully
i  firestore: checking firestore.rules for compilation errors...
✔  firestore: rules file firestore.rules compiled successfully
i  storage: uploading rules storage.rules...
i  firestore: uploading rules firestore.rules...
i  hosting[friendlychat-1234]: beginning deploy...
i  hosting[friendlychat-1234]: found 8 files in ./public
✔  hosting[friendlychat-1234]: file upload complete
✔  storage: released rules storage.rules to firebase.storage/friendlychat-1234.appspot.com
✔  firestore: released rules firestore.rules to cloud.firestore
i  hosting[friendlychat-1234]: finalizing version...
✔  hosting[friendlychat-1234]: version finalized
i  hosting[friendlychat-1234]: releasing new version...
✔  hosting[friendlychat-1234]: release complete

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview
Hosting URL: https://friendlychat-1234.firebaseapp.com
  1. 独自の Firebase サブドメインの 2 つで Firebase Hosting を使用して、グローバル CDN で完全にホストされているウェブアプリにアクセスします。
  • https://<firebase-projectId>.firebaseapp.com
  • https://<firebase-projectId>.web.app

あるいは、コマンドラインでfirebase open hosting:siteを実行することもできます。

Firebase Hosting の仕組みの詳細については、ドキュメントを参照してください。

プロジェクトの Firebase コンソールの [ホスティング]セクションに移動すると、デプロイの履歴、アプリの前のバージョンにロールバックする機能、カスタム ドメインを設定するワークフローなど、役立つホスティング情報とツールが表示されます。

15. おめでとうございます!

Firebase を使用してリアルタイム チャット Web アプリケーションを構築しました。

カバーした内容

  • Firebase認証
  • クラウドファイアストア
  • クラウド ストレージ用 Firebase SDK
  • Firebase クラウド メッセージング
  • Firebaseのパフォーマンスモニタリング
  • Firebaseホスティング

次のステップ

もっと詳しく知る

16. (オプション) App Check による強制

Firebase App Check は、サービスを不要なトラフィックから保護し、バックエンドを悪用から保護するのに役立ちます。このステップでは、認証情報の検証を追加し、App Check とreCAPTCHA Enterpriseを使用して未承認のクライアントをブロックします。

まず、App Check と reCaptcha を有効にする必要があります。

reCaptcha Enterprise の有効化

  1. Cloud コンソールで、「セキュリティ」の下にある「reCaptcha Enterprise」を見つけて選択します。
  2. プロンプトに従ってサービスを有効にし、 「キーの作成」をクリックします。
  3. プロンプトに従って表示名を入力し、プラットフォームの種類として[Web サイト]を選択します。
  4. デプロイした URL をドメイン リストに追加し、[チェックボックス チャレンジを使用する] オプションが選択されていないことを確認します。
  5. [キーの作成]をクリックし、生成されたキーを安全な場所に保存します。このステップの後半で必要になります。

アプリチェックを有効にする

  1. Firebase コンソールの左側のパネルで[ビルド]セクションを見つけます。
  2. [App Check]をクリックし、 [サインイン方法]タブをクリックして[App Check]に移動します。
  3. [登録]をクリックし、プロンプトが表示されたら reCaptcha Enterprise キーを入力し、 [保存]をクリックします。
  4. API ビューで、 「ストレージ」を選択し、 「強制」をクリックします。 Cloud Firestoreに対しても同じことを行います。

アプリチェックが強制されるようになりました。アプリを更新して、チャット メッセージを表示または送信してみます。次のエラー メッセージが表示されるはずです。

Uncaught Error in snapshot listener: FirebaseError: [code=permission-denied]: Missing or insufficient permissions.

これは、App Check がデフォルトで未検証のリクエストをブロックしていることを意味します。次に、アプリに検証を追加しましょう。

environment.tsファイルに移動し、 reCAPTCHAEnterpriseKeyenvironmentオブジェクトに追加します。

export const environment = {
  firebase: {
    apiKey: 'API_KEY',
    authDomain: 'PROJECT_ID.firebaseapp.com',
    databaseURL: 'https://PROJECT_ID.firebaseio.com',
    projectId: 'PROJECT_ID',
    storageBucket: 'PROJECT_ID.appspot.com',
    messagingSenderId: 'SENDER_ID',
    appId: 'APP_ID',
    measurementId: 'G-MEASUREMENT_ID',
  },
  reCAPTCHAEnterpriseKey: {
    key: "Replace with your recaptcha enterprise site key"
  },
};

keyの値を reCaptcha Enterprise トークンに置き換えます。

次に、 app.module.tsファイルに移動し、次のインポートを追加します。

import { getApp } from '@angular/fire/app';
import {
  ReCaptchaEnterpriseProvider,
  initializeAppCheck,
  provideAppCheck,
} from '@angular/fire/app-check';

同じapp.module.tsファイルに、次のグローバル変数宣言を追加します。

declare global {
  var FIREBASE_APPCHECK_DEBUG_TOKEN: boolean;
}

@NgModule({ ...

インポートで、 ReCaptchaEnterpriseProviderを使用した App Check の初期化を追加し、 isTokenAutoRefreshEnabledtrueに設定してトークンの自動更新を許可します。

imports: [
BrowserModule,
AppRoutingModule,
CommonModule,
FormsModule,
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAppCheck(() => {
const appCheck = initializeAppCheck(getApp(), {
  provider: new ReCaptchaEnterpriseProvider(
  environment.reCAPTCHAEnterpriseKey.key
  ),
  isTokenAutoRefreshEnabled: true,
  });
  if (location.hostname === 'localhost') {
    self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
  }
  return appCheck;
}),

ローカル テストを許可するには、 self.FIREBASE_APPCHECK_DEBUG_TOKENtrueに設定します。 localhostでアプリを更新すると、次のようなデバッグ トークンがコンソールに記録されます。

App Check debug token: CEFC0C76-7891-494B-B764-349BDFD00D00. You will need to add it to your app's App Check settings in the Firebase console for it to work.

次に、Firebase コンソールの App Check のアプリ ビューに移動します。

オーバーフロー メニューをクリックし、 [デバッグ トークンの管理]を選択します。

次に、 [デバッグ トークンの追加]をクリックし、プロンプトに従ってコンソールからデバッグ トークンを貼り付けます。

chat.service.tsファイルに移動し、次のインポートを追加します。

import { AppCheck } from '@angular/fire/app-check';

同じchat.service.tsファイルに、他の Firebase サービスと一緒に App Check を挿入します。

export class ChatService {
appCheck: AppCheck = inject(AppCheck);
...

おめでとう!これで、アプリ内で App Check が機能するはずです。