FirebaseWebコードラボ

1。概要

この Codelab では、Firebase の製品とサービスを使用してチャット クライアントを実装およびデプロイすることで、 Firebase を使用してウェブ アプリケーションを簡単に作成する方法を学びます。

3b1284f5144b54f6.png

学習内容

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

必要なもの

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

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

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

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

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

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

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

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

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

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

これから構築するアプリケーションは、Web アプリで利用可能な Firebase 製品を使用します。

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

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

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

  1. Web アイコンをクリックします。 58d6543a156e56f9.png新しい Firebase Web アプリを作成します。
  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. [テスト モードで開始]オプションを選択し、セキュリティ ルールに関する免責事項を読んだ後、 [次へ]をクリックします。

テストモードにより、開発中にデータベースに自由に書き込むことができます。この Codelab の後半で、データベースをより安全にします。

77e4986cbeaf9dee.png

  1. Cloud Firestore データが保存される場所を設定します。これをデフォルトのままにするか、最寄りのリージョンを選択できます。 [完了]をクリックして、Firestore をプロビジョニングします。

9f2bb0d4e7ca49c7.png

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

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

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

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

デフォルトのセキュリティ ルールでは、認証されたユーザーは Cloud Storage に何でも書き込むことができます。この Codelab の後半で、ストレージをより安全にします。

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 用のアプリの構成をアプリのローカル ディレクトリ (前の Codelab でクローンを作成したリポジトリ) からプルするように、ウェブアプリ テンプレートをセットアップしました。ただし、構成をプルするには、アプリを Firebase プロジェクトに関連付ける必要があります。

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

エイリアスは、複数の環境 (本番、ステージングなど) がある場合に役立ちます。ただし、この Codelab では、 defaultのエイリアスだけを使用しましょう。

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

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

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

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

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

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

(まだ!) 機能していない FriendlyChat アプリの UI が表示されます。

4c23f9475228cef4.png

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

それでは、リアルタイム チャットを作成しましょう。

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

Firebase SDK をインポートする

Firebase SDK をアプリにインポートする必要があります。ドキュメント で説明されているように、これを行うには複数の方法があります。たとえば、CDN からライブラリをインポートできます。または、npm を使用してローカルにインストールし、Br​​owserify を使用している場合はアプリにパッケージ化することもできます。

npm から Firebase SDK を取得し、 Webpackを使用してコードをバンドルします。これは、Webpack が不要なコードを削除し、JS バンドルのサイズを小さくして、アプリができるだけ速く読み込まれるようにするためです。この Codelab では、Firebase SDK を依存関係として含むweb-start/package.jsonファイルを既に作成し、必要な関数をweb-start/src/index.jsの上部にインポートしました。

パッケージ.json

"dependencies": {
  "firebase": "^9.0.0"
}

index.js

import { initializeApp } from 'firebase/app';
import {
  getAuth,
  onAuthStateChanged,
  GoogleAuthProvider,
  signInWithPopup,
  signOut,
} from 'firebase/auth';
import {
  getFirestore,
  collection,
  addDoc,
  query,
  orderBy,
  limit,
  onSnapshot,
  setDoc,
  updateDoc,
  doc,
  serverTimestamp,
} from 'firebase/firestore';
import {
  getStorage,
  ref,
  uploadBytesResumable,
  getDownloadURL,
} from 'firebase/storage';
import { getMessaging, getToken, onMessage } from 'firebase/messaging';
import { getPerformance } from 'firebase/performance';

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

Firebase SDK をインストールして Webpack ビルドを開始する

アプリのビルドを開始するには、いくつかのコマンドを実行する必要があります。

  1. 新しいターミナル ウィンドウを開く
  2. web-startディレクトリにいることを確認してください
  3. npm installを実行して Firebase SDK をダウンロードします
  4. npm run startを実行して Webpack を起動します。 Webpack は、コードラボの残りの部分でソース コードを継続的に再構築します。

Firebase を構成する

また、使用している Firebase プロジェクトを伝えるために、Firebase SDK を構成する必要があります。

  1. Firebase コンソールでプロジェクト設定に移動します
  2. [あなたのアプリ] カードで、構成オブジェクトが必要なアプリのニックネームを選択します。
  3. Firebase SDK スニペット ペインから [Config] を選択します。
  4. config オブジェクトのスニペットをコピーして、 web-start/src/firebase-config.jsに追加します。

firebase-config.js

const config = {
  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",
};

次に、 web-start/src/index.jsの一番下に移動し、Firebase を初期化します。

index.js

const firebaseAppConfig = getFirebaseConfig();
initializeApp(firebaseAppConfig);

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

index.jsでインポートおよび初期化されているため、Firebase SDK を使用する準備ができているはずです。 Firebase Authenticationを使用してユーザー サインインを実装します。

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

アプリで、ユーザーが[Google でサインイン]ボタンをクリックすると、 signIn関数がトリガーされます。 (すでに設定済みです!) この Codelab では、Firebase が Google を ID プロバイダーとして使用することを承認します。ここではポップアップを使用しますが、Firebase には他にもいくつかの方法があります。

  1. web-startディレクトリのサブディレクトリsrc/で、 index.jsを開きます。
  2. 関数signIn見つけます。
  3. 関数全体を次のコードに置き換えます。

index.js

// Signs-in Friendly Chat.
async function signIn() {
  // Sign in Firebase using popup auth and Google as the identity provider.
  var provider = new GoogleAuthProvider();
  await signInWithPopup(getAuth(), provider);
}

ユーザーが[サインアウト]ボタンをクリックすると、 signOut関数がトリガーされます。

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

index.js

// Signs-out of Friendly Chat.
function signOutUser() {
  // Sign out of Firebase.
  signOut(getAuth());
}

認証状態を追跡する

それに応じて UI を更新するには、ユーザーがサインインしているかサインアウトしているかを確認する方法が必要です。 Firebase Authentication を使用すると、認証状態が変化するたびにトリガーされる認証状態にオブザーバーを登録できます。

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

index.js

// Initialize firebase auth
function initFirebaseAuth() {
  // Listen to auth state changes.
  onAuthStateChanged(getAuth(), authStateObserver);
}

上記のコードは、関数authStateObserver認証状態オブザーバーとして登録します。認証状態が変化するたびにトリガーされます (ユーザーがサインインまたはサインアウトするとき)。この時点で、UI を更新して、サインイン ボタン、サインアウト ボタン、サインインしているユーザーのプロフィール画像などを表示または非表示にします。これらの UI パーツはすべて実装済みです。

サインインしているユーザーの情報を表示する

サインインしているユーザーのプロフィール写真とユーザー名をアプリのトップ バーに表示したいと考えています。 Firebase では、サインインしているユーザーのデータは常にcurrentUserオブジェクトで利用できます。以前に、ユーザーがサインインしたときにトリガーするようにauthStateObserver関数を設定して、それに応じて UI が更新されるようにしました。トリガーされると、 getProfilePicUrlgetUserNameが呼び出されます。

  1. ファイルsrc/index.jsに戻ります。
  2. 関数getProfilePicUrlおよびgetUserNameを見つけます。
  3. 両方の関数を次のコードに置き換えます。

index.js

// Returns the signed-in user's profile Pic URL.
function getProfilePicUrl() {
  return getAuth().currentUser.photoURL || '/images/profile_placeholder.png';
}

// Returns the signed-in user's display name.
function getUserName() {
  return getAuth().currentUser.displayName;
}

ユーザーがサインインしていないときにメッセージを送信しようとすると、エラー メッセージが表示されます (試すことはできます)。そのため、ユーザーが実際にサインインしているかどうかを検出する必要があります。

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

index.js

// Returns true if a user is signed-in.
function isUserSignedIn() {
  return !!getAuth().currentUser;
}

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

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

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

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

データ・モデル

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

688d7bc5fb662b57.png

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

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

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

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

index.js

// Saves a new message to Cloud Firestore.
async function saveMessage(messageText) {
  // Add a new message entry to the Firebase database.
  try {
    await addDoc(collection(getFirestore(), 'messages'), {
      name: getUserName(),
      text: messageText,
      profilePicUrl: getProfilePicUrl(),
      timestamp: serverTimestamp()
    });
  }
  catch(error) {
    console.error('Error writing new message to Firebase Database', error);
  }
}

メッセージ送信のテスト

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

6812efe7da395692.png

9. メッセージを読む

メッセージを同期する

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

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

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

index.js

// Loads chat messages history and listens for upcoming ones.
function loadMessages() {
  // Create the query to load the last 12 messages and listen for new ones.
  const recentMessagesQuery = query(collection(getFirestore(), 'messages'), orderBy('timestamp', 'desc'), limit(12));
  
  // Start listening to the query.
  onSnapshot(recentMessagesQuery, 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);
      }
    });
  });
}

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

onSnapshot関数は、クエリを最初のパラメーターとして受け取り、コールバック関数を 2 番目のパラメーターとして受け取ります。クエリに一致するドキュメントに変更があると、コールバック関数がトリガーされます。これは、メッセージが削除、変更、または追加された場合に発生する可能性があります。詳細については、Cloud Firestore のドキュメントをご覧ください。

同期メッセージのテスト

  1. アプリがまだ提供されている場合は、ブラウザーでアプリを更新します。それ以外の場合は、コマンド ラインでfirebase serve --only hosting実行してhttp://localhost:5000からアプリの提供を開始し、ブラウザーで開きます。
  2. 前にデータベースに作成したメッセージは、FriendlyChat UI に表示されます (以下を参照)。新しいメッセージを自由に書き込んでください。それらはすぐに表示されるはずです。
  3. (省略可) Firebase コンソールの[データベース]セクションで、新しいメッセージを直接手動で削除、変更、または追加することができます。変更はすべて UI に反映される必要があります。

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

2168dec79b573d07.png

10. 画像を送る

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

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

画像を Cloud Storage に保存する

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

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

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

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

index.js

// Saves a new message containing an image in Firebase.
// This first saves the image in Firebase storage.
async function saveImageMessage(file) {
  try {
    // 1 - We add a message with a loading icon that will get updated with the shared image.
    const messageRef = await addDoc(collection(getFirestore(), 'messages'), {
      name: getUserName(),
      imageUrl: LOADING_IMAGE_URL,
      profilePicUrl: getProfilePicUrl(),
      timestamp: serverTimestamp()
    });

    // 2 - Upload the image to Cloud Storage.
    const filePath = `${getAuth().currentUser.uid}/${messageRef.id}/${file.name}`;
    const newImageRef = ref(getStorage(), 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.
    await updateDoc(messageRef,{
      imageUrl: publicImageUrl,
      storageUri: fileSnapshot.metadata.fullPath
    });
  } catch (error) {
    console.error('There was an error uploading a file to Cloud Storage:', error);
  }
}

画像のテスト送信

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

サインインしていない状態で画像を追加しようとすると、画像を追加するにはサインインする必要があることを示すトースト通知が表示されます。

11.通知を表示する

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

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

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

  1. web-startディレクトリのsrcディレクトリで、 firebase-messaging-sw.jsを開きます。
  2. そのファイルに次の内容を追加します。

firebase-messaging-sw.js

// Import and configure the Firebase SDK
import { initializeApp } from 'firebase/app';
import { getMessaging } from 'firebase/messaging/sw';
import { getFirebaseConfig } from './firebase-config';

const firebaseApp = initializeApp(getFirebaseConfig());
getMessaging(firebaseApp);
console.info('Firebase messaging service worker is set up');

Service Worker は、通知の表示を処理する Firebase Cloud Messaging SDK を読み込んで初期化するだけです。

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

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

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

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

index.js

// Saves the messaging device token to Cloud Firestore.
async function saveMessagingDeviceToken() {
  try {
    const currentToken = await getToken(getMessaging());
    if (currentToken) {
      console.log('Got FCM device token:', currentToken);
      // Saving the Device Token to Cloud Firestore.
      const tokenRef = doc(getFirestore(), 'fcmTokens', currentToken);
      await setDoc(tokenRef, { uid: getAuth().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(getMessaging(), (message) => {
        console.log(
          'New foreground notification from Firebase Messaging!',
          message.notification
        );
      });
    } else {
      // Need to request permissions to show notifications.
      requestNotificationsPermissions();
    }
  } catch(error) {
    console.error('Unable to get messaging token.', error);
  };
}

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

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

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

8b9d0c66dc36153d.png

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

index.js

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

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

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

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

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

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

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

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

de79e8638a45864c.png

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

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

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

この Codelab の開始時に 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;
    }
  }
}

データベース セキュリティ ルールの更新

データベース セキュリティ ルールを編集するには、Firebase コンソールで編集する方法と、Firebase CLI を使用してデプロイされたローカル ルール ファイルから編集する方法の 2 つがあります。

Firebase コンソールでセキュリティ ルールを更新するには:

  1. 左側のパネルから[データベース]セクションに移動し、 [ルール]タブをクリックします。
  2. コンソールに既にあるデフォルトのルールを上記のルールに置き換えます。
  3. [公開]をクリックします。

ローカル ファイルからセキュリティ ルールを更新するには:

  1. web-startディレクトリから、 firestore.rulesを開きます。
  2. ファイルに既にあるデフォルトのルールを上記のルールに置き換えます。
  3. web-startディレクトリから、 firebase.jsonを開きます。
  4. 以下に示すように、 firestore.rulesを指すfirestore.rules属性を追加します。 ( hosting属性は既にファイルに含まれている必要があります。)

firebase.json

{
  // Add this!
  "firestore": {
    "rules": "firestore.rules"
  },
  "hosting": {
    "public": "./public"
  }
}
  1. 次のコマンドを実行して、Firebase CLI を使用してセキュリティ ルールをデプロイします。
firebase deploy --only firestore
  1. コマンド ラインに次の応答が表示されます。
=== Deploying to 'friendlychat-1234'...

i  deploying firestore
i  firestore: checking firestore.rules for compilation errors...
✔  firestore: rules file firestore.rules compiled successfully
i  firestore: uploading rules firestore.rules...
✔  firestore: released rules firestore.rules to cloud.firestore

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

13. Cloud Storage のセキュリティ ルール

Cloud Storage セキュリティ ルールを表示する

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

この Codelab の最初に 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 に制限する

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

storage.rules

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;
    }
  }
}

Cloud Storage セキュリティ ルールを更新する

ストレージ セキュリティ ルールを編集するには、Firebase コンソールで編集する方法と、Firebase CLI を使用してデプロイされたローカル ルール ファイルから編集する方法の 2 つがあります。

Firebase コンソールでセキュリティ ルールを更新するには:

  1. 左側のパネルから[ストレージ]セクションに移動し、 [ルール]タブをクリックします。
  2. コンソールに既にあるデフォルトのルールを上記のルールに置き換えます。
  3. [公開]をクリックします。

ローカル ファイルからセキュリティ ルールを更新するには:

  1. web-startディレクトリから、 storage.rulesを開きます。
  2. ファイルに既にあるデフォルトのルールを上記のルールに置き換えます。
  3. web-startディレクトリから、 firebase.jsonを開きます。
  4. 次に示すように、 storage.rulesファイルを指すstorage.rules属性を追加します。 ( hostingおよびdatabase属性は、ファイルに既に含まれている必要があります。)

firebase.json

{
  // If you went through the "Cloud Firestore Security Rules" step.
  "firestore": {
    "rules": "firestore.rules"
  },
  // Add this!
  "storage": {
    "rules": "storage.rules"
  },
  "hosting": {
    "public": "./public"
  }
}
  1. 次のコマンドを実行して、Firebase CLI を使用してセキュリティ ルールをデプロイします。
firebase deploy --only storage
  1. コマンド ラインに次の応答が表示されます。
=== Deploying to 'friendlychat-1234'...

i  deploying storage
i  storage: checking storage.rules for compilation errors...
✔  storage: rules file storage.rules compiled successfully
i  storage: uploading rules storage.rules...
✔  storage: released rules storage.rules to firebase.storage/friendlychat-1234.appspot.com

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/friendlychat-1234/overview

14. パフォーマンス データを収集する

Performance Monitoring SDK を使用してアプリから実際のパフォーマンス データを収集し、Firebase コンソールでそのデータを確認して分析できます。 Performance Monitoring は、アプリのパフォーマンスをいつどこで改善できるかを理解し、その情報を使用してパフォーマンスの問題を修正できるようにするのに役立ちます。

Firebase Performance Monitoring JavaScript SDK と統合するには、さまざまな方法があります。このコードラボでは、ホスティング URLからのパフォーマンス モニタリングを有効にしました。 SDK を有効にする他の方法については、ドキュメントを参照してください。

自動トレース

getPerformance web-start/src/index.jsの先頭に既にインポートされているため、1 行追加するだけで、ユーザーがデプロイされたサイトにアクセスしたときにページの読み込みとネットワーク リクエストのメトリックを自動的に収集するよう Performance Monitoring に指示することができます。

  1. web-start/src/index.jsで、既存のTODOの下に次の行を追加して、Performance Monitoring を初期化します。

index.js

// TODO: Enable Firebase Performance Monitoring.
getPerformance();

最初の入力遅延の測定 (オプション)

ユーザー インタラクションに応答するブラウザーは、アプリの応答性に関する第一印象をユーザーに与えるため、初回入力遅延は役立ちます。

最初の入力遅延は、ボタンやハイパーリンクのクリックなど、ユーザーがページ上の要素を最初に操作したときに始まります。ブラウザーが入力に応答できるようになるとすぐに停止します。つまり、ブラウザーがページのコンテンツの読み込みや解析でビジー状態ではないことを意味します。

最初の入力遅延を測定したい場合は、次のコードを直接含める必要があります。

  1. public/index.htmlを開きます。
  2. 次の行のscriptタグのコメントを外します。

index.html

<!-- TODO: Enable First Input Delay polyfill library. -->
<script type="text/javascript">!function(n,e){var t,o,i,c=[],f={passive:!0,capture:!0},r=new Date,a="pointerup",u="pointercancel";function p(n,c){t||(t=c,o=n,i=new Date,w(e),s())}function s(){o>=0&&o<i-r&&(c.forEach(function(n){n(o,t)}),c=[])}function l(t){if(t.cancelable){var o=(t.timeStamp>1e12?new Date:performance.now())-t.timeStamp;"pointerdown"==t.type?function(t,o){function i(){p(t,o),r()}function c(){r()}function r(){e(a,i,f),e(u,c,f)}n(a,i,f),n(u,c,f)}(o,t):p(o,t)}}function w(n){["click","mousedown","keydown","touchstart","pointerdown"].forEach(function(e){n(e,l,f)})}w(n),self.perfMetrics=self.perfMetrics||{},self.perfMetrics.onFirstInputDelay=function(n){c.push(n),s()}}(addEventListener,removeEventListener);</script>

最初の入力遅延ポリフィルの詳細については、ドキュメントを参照してください。

パフォーマンス データを表示する

サイトをまだデプロイしていないため (次のステップでデプロイします)、ユーザーがデプロイされたサイトを操作してから 30 分以内に Firebase コンソールに表示されるページ読み込みパフォーマンスに関するメトリックを示すスクリーンショットを次に示します。 :

29389131150f33d7.png

Performance Monitoring SDK をアプリに統合すると、アプリがパフォーマンスのいくつかの重要な側面を自動的に監視し始める前に、他のコードを記述する必要はありません。 Web アプリの場合、SDK は最初のコンテンツ ペイント、ユーザーがアプリを操作する機能などの側面をログに記録します。

カスタム トレース、メトリック、および属性を設定して、アプリの特定の側面を測定することもできます。カスタム トレースとメトリック、およびカスタム属性の詳細については、ドキュメントを参照してください。

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

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

firebase.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ディレクトリ ( "public": "./public" ) にすべてのファイルをデプロイすることを CLI に伝えます。

  1. コマンドラインがアプリのローカルweb-startディレクトリにアクセスしていることを確認してください。
  2. 次のコマンドを実行して、ファイルを Firebase プロジェクトにデプロイします。
firebase deploy --except functions
  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. 2 つの独自の Firebase サブドメインで Firebase Hosting を使用して、グローバル CDN で完全にホストされているウェブ アプリにアクセスします。
  • https://<firebase-projectId>.firebaseapp.com
  • https://<firebase-projectId>.web.app

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

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

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

16.おめでとう!

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

カバーした内容

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

次のステップ

Learn more