AngularFire 網頁程式碼研究室

1. 總覽

在本程式碼研究室中,您將瞭解如何透過使用 Firebase 產品和服務實作及部署即時通訊用戶端,藉此透過 AngularFire 建立網頁應用程式。

使用者正在討論 Firebase 的即時通訊應用程式

實驗室內容

  • 使用 Angular 和 Firebase 建構網頁應用程式。
  • 透過 Cloud Firestore 和 Cloud Storage for Firebase 同步處理資料。
  • 使用 Firebase 驗證功能來驗證使用者。
  • 在 Firebase App Hosting 部署網頁應用程式。
  • 使用 Firebase 雲端通訊傳送通知。
  • 收集網頁應用程式的效能資料。

事前準備

  • GitHub 帳戶
  • 能將 Firebase 專案升級至 Blaze 定價方案
  • 您選擇的 IDE/文字編輯器,例如 WebStormSublimeVS Code
  • 套件管理員 npm,通常隨附於 Node.js
  • 終端機/控制台
  • 您選擇的瀏覽器,例如 Chrome
  • 程式碼研究室的程式碼範例 (請參閱程式碼研究室的下一步,瞭解如何取得程式碼)。

2. 取得程式碼範例

建立 GitHub 存放區

您可以在 https://github.com/firebase/codelab-friendlychat-web 找到程式碼研究室原始碼。這個存放區包含多個平台的範例專案。不過,本程式碼研究室只會使用 angularfire-start 目錄。

angularfire-start 資料夾複製到自己的存放區:

  1. 使用終端機,在電腦上建立新資料夾並切換至新目錄:
    mkdir codelab-friendlyeats-web
    
    cd codelab-friendlyeats-web
    
  2. 使用 giget npm 套件僅擷取 angularfire-start 資料夾:
    npx giget@latest gh:firebase/codelab-friendlychat-web/angularfire-start#master . --install
    
  3. 使用 Git 在本機追蹤變更:
    git init
    
    git add .
    
    git commit -m "codelab starting point"
    
    git branch -M main
    
  4. 建立新的 GitHub 存放區:https://github.com/new。命名方式。
    1. GitHub 將提供新的存放區網址,形式類似 https://github.com/[user-name]/[repository-name].gitgit@github.com:[user-name]/[repository-name].git。請複製這個網址。
  5. 將本機變更推送至新的 GitHub 存放區。執行下列指令,將 your-repository-url 預留位置改成存放區網址。
    git remote add origin your-repository-url
    
    git push -u origin main
    
  6. 您現在應該會在 GitHub 存放區中看到範例程式碼。

3. 建立及設定 Firebase 專案

建立 Firebase 專案

  1. 登入 Firebase 控制台
  2. 在 Firebase 控制台中,按一下「新增專案」,然後將 Firebase 專案命名為「friendlyChat」。記下 Firebase 專案的專案 ID。
  3. 取消勾選「為這項專案啟用 Google Analytics (分析)」
  4. 按一下 [Create Project] (建立專案)

您要建構的應用程式使用了適用於網頁應用程式的 Firebase 產品:

  • Firebase 驗證:方便使用者登入您的應用程式。
  • Cloud Firestore,可將結構化資料儲存至雲端,並在資料變更時立即發送通知。
  • Cloud Storage for Firebase,將檔案儲存在雲端。
  • Firebase App Hosting 建構、代管和提供應用程式。
  • Firebase 雲端通訊:用來傳送推播通知,並顯示瀏覽器彈出式視窗通知。
  • Firebase 效能監控:收集您應用程式的使用者效能資料。

部分產品需要特殊設定,或透過 Firebase 控制台啟用。

升級 Firebase 定價方案

如要使用 App Hosting,您的 Firebase 專案必須採用 Blaze 定價方案,這代表專案已與 Cloud Billing 帳戶建立關聯。

  • Cloud Billing 帳戶需要付款方式,例如信用卡。
  • 如果您是 Firebase 和 Google Cloud 新手,請確認您是否符合取得 $300 美元的抵免額和 Cloud Billing 免費試用帳戶的資格。

如要將專案升級至 Blaze 方案,請按照下列步驟操作:

  1. 在 Firebase 控制台中,選取升級方案
  2. 在對話方塊中選取 Blaze 方案,然後按照畫面上的指示將專案連結至 Cloud Billing 帳戶。
    如需建立 Cloud Billing 帳戶,您可能需要返回 Firebase 控制台的升級流程。

將 Firebase 網頁應用程式新增至專案

  1. 按一下網站圖示 58d6543a156e56f9.png,建立新的 Firebase 網頁應用程式。
  2. 使用「friendly Chat」註冊應用程式。不勾選「一併為這個應用程式設定 Firebase 託管」旁的方塊,按一下「註冊應用程式」
  3. 在下一個步驟中,您會看到設定物件。目前你不需要用到。按一下 [Continue to console] (前往主控台)。

註冊網頁應用程式的螢幕截圖

設定驗證

如要允許使用者以 Google 帳戶登入網頁應用程式,請使用 Google 登入方式。

  1. 在 Firebase 控制台中,前往「驗證」
  2. 按一下「開始」
  3. 在「其他供應商」欄中,依序按一下「Google」>「啟用」
  4. 在「Public-face name for project」(專案公開名稱) 文字方塊中,輸入一個好記的名稱,例如 My Next.js app
  5. 在「專案支援電子郵件」下拉式選單中,選取您的電子郵件地址。
  6. 按一下「儲存」

啟用 Cloud Firestore

網頁應用程式會使用 Cloud Firestore 儲存即時通訊訊息及接收新的即時通訊訊息。

您必須啟用 Cloud Firestore:

  1. 在 Firebase 控制台中,前往「Firestore」
  2. 依序點選「建立資料庫」>「下一步」>「以測試模式啟動」>「下一步」
    在本程式碼研究室中,您將新增安全性規則來保護資料。請勿在未新增資料庫安全性規則的情況下公開發行或發布應用程式。
  3. 請使用預設位置或選取你選擇的位置。
    如果是實際的應用程式,建議你選擇靠近使用者的位置。請注意,這個位置在之後無法變更,並且會自動是預設 Cloud Storage 值區的位置 (下一步)。
  4. 點選「完成」

啟用 Cloud Storage

網頁應用程式會使用 Cloud Storage for Firebase 儲存、上傳及分享相片。

您必須啟用 Cloud Storage:

  1. 在 Firebase 控制台中,前往「Storage」(儲存空間)
  2. 依序點選「開始使用」>「以測試模式啟動」>「下一步」
    在本程式碼研究室的後續部分,您要新增安全性規則來保護資料。請勿在未新增 Storage 值區的安全性規則的情況下公開發行或發布應用程式。
  3. 您必須選取值區的位置 (因為上一個步驟已設定 Firestore)。
  4. 點選「完成」

4. 安裝 Firebase 指令列介面

透過 Firebase 指令列介面 (CLI),你可以使用 Firebase 託管功能在本機提供網頁應用程式,並將網頁應用程式部署至 Firebase 專案。

  1. 執行下列 npm 指令安裝 CLI:
npm -g install firebase-tools@latest
  1. 執行下列指令,確認 CLI 已正確安裝:
firebase --version

確認 Firebase CLI 的版本為 v13.9.0 以上版本。

  1. 執行下列指令來授權 Firebase CLI:
firebase login

您已設定網頁應用程式範本,從應用程式的本機目錄 (先前在程式碼研究室中複製的存放區) 提取 Firebase 託管的應用程式設定。不過,如要提取設定,您必須將應用程式與 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. 當系統提示時,使用空白鍵取消勾選 ng deploy -- hosting。使用方向鍵和空格鍵選取下列功能:
    • Authentication
    • Firestore
    • Cloud Messaging
    • Cloud Storage
  2. 按下 enter 鍵,然後按照後續提示操作。
  3. 建立含有修訂訊息「Install AngularFire」的修訂版本,並推送至 GitHub 存放區。

6. 建立 App Hosting 後端

在本節中,您將設定 App Hosting 後端,監控 Git 存放區中的分支版本。

本節結束時,您的 App Hosting 後端會連結至 GitHub 中的存放區。每當您將新的修訂版本推送至 main 分支版本時,系統就會自動重建並推出新版應用程式。

  1. 前往 Firebase 控制台的 App Hosting 頁面

App Hosting 控制台的零狀態,畫面上有「Get Started」按鈕

  1. 點選「開始使用」,啟動後端建立流程。請按照下列方式設定後端:
  2. 按照第一個步驟的提示,連結您先前建立的 GitHub 存放區。
  3. 進行部署作業設定:
    1. 將根目錄保留為 /
    2. 將使用中的分支版本設為「main
    3. 啟用自動推出功能
  4. 為後端 friendlychat-codelab 命名。
  5. 在「建立或連結 Firebase 網頁應用程式」中,從「選取現有的 Firebase 網頁應用程式」下拉式選單中,選取先前設定的網頁應用程式。
  6. 按一下「完成並部署」。稍後系統會將您導向新頁面,您可以在此查看新 App Hosting 後端的狀態!
  7. 推出作業完成後,請在「網域」下方按一下免費網域。由於 DNS 傳播,這項作業可能需要幾分鐘才會開始運作。

您已成功部署初始網頁應用程式!每次將新修訂版本推送至 GitHub 存放區的 main 分支版本時,Firebase 控制台中就會顯示新的版本與推出作業,並在推出完成後自動更新您的網站。

App Hosting 控制台的零狀態,畫面上有「Get Started」按鈕

您應該會看到 LoyaltyChat 應用程式的登入畫面,目前尚無法正常運作。

應用程式目前尚無法執行任何操作,但在您的協助下,我們很快就會開始運作!

讓我們開始建構即時通訊應用程式。

7. 匯入及設定 Firebase

設定 Firebase

您必須設定 Firebase SDK,讓 SDK 知道您使用的 Firebase 專案。

  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",
    projectId: "PROJECT_ID",
    storageBucket: "PROJECT_ID.appspot.com",
    messagingSenderId: "SENDER_ID",
    appId: "APP_ID",
  },
};

查看 AngularFire 設定

您在控制台中選取的功能已自動新增至 /angularfire-start/src/app/app.config.ts 檔案。這樣一來,應用程式就能使用 Firebase 的功能。

8. 設定使用者登入

AngularFire 已經在 app.config.ts 中匯入並初始化,因此應隨時可供使用。您現在會使用 Firebase 驗證實作使用者登入程序。

新增授權網域

Firebase 驗證只允許從你所控管的網域清單中登入。將免費的 App Hosting 網域新增至網域清單:

  1. 前往「App Hosting」
  2. 複製您後端的網域。
  3. 前往「驗證設定」
  4. 選擇「授權網域」分頁標籤。
  5. 按一下「Add domain」(新增網域),然後貼上 App Hosting 後端的網域。

使用 Google 登入功能驗證使用者

在應用程式中點選「使用 Google 帳戶登入」按鈕時,會觸發 login 函式。在本程式碼研究室中,您要授權 Firebase 使用 Google 做為識別資訊提供者。您將使用彈出式視窗,但 Firebase 提供其他幾種方法

  1. 在子目錄 /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;
    })
}

使用者按一下「Log out」按鈕時,即會觸發 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);
    })
}

追蹤驗證狀態

如要據此更新使用者介面,您需要一種方法檢查使用者是否已登入或登出。AngularFire 提供一項函式,用於取得可觀測的資料,這個可觀測項目會在每次驗證狀態變更時更新。先前已實作過,但還是值得參考。

  1. 返回 src/app/services/chat.service.ts 檔案。
  2. 找出變數指派 user$

chat.service.ts

// observable that is updated when the auth state changes
user$ = user(this.auth);

上述程式碼會呼叫 AngularFire 函式 user,此函式會傳回可觀察使用者。每當驗證狀態變更 (使用者登入或登出) 時就會觸發。chromiumChat 中的 Angular 範本元件會使用這個可觀察項目來更新使用者介面,以及在標頭導覽中顯示使用者,以此類推。

測試登入應用程式

  1. 建立含有修訂訊息「Add Google Authentication」的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。
  3. 在網頁應用程式中,重新整理網頁,然後使用登入按鈕和 Google 帳戶登入應用程式。如果出現「auth/operation-not-allowed」的錯誤訊息,請確認您已在 Firebase 控制台啟用 Google 登入做為驗證供應商。
  4. 登入後,畫面上應該會顯示你的個人資料相片和使用者名稱:angularfire-3.png

9. 將訊息寫入 Cloud Firestore

在本節中,您會寫入一些資料至 Cloud Firestore,以填入應用程式的 UI。你可以透過 Firebase 控制台手動執行這項作業,但需要在應用程式中進行這項作業,才能示範基本的 Cloud Firestore 寫入方式。

資料模型

Cloud Firestore 的資料分成集合、文件、欄位和子集合。您將每則即時通訊訊息儲存為文件,並儲存在名為 messages 的頂層集合中。

688d7bc5fb662b57.png

將訊息新增至 Cloud Firestore

如要儲存使用者寫入的即時通訊訊息,請使用 Cloud Firestore

在本節中,您將新增功能,讓使用者能夠將新訊息寫入資料庫。使用者按一下「傳送」按鈕,就會觸發下方的程式碼片段。這會將含有訊息欄位內容的訊息物件新增至 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>> => {
  // ignore empty messages
  if (!textMessage && !imageUrl) {
    console.log(
      "addMessage was called without a message",
      textMessage,
      imageUrl,
    );
    return;
  }

  if (this.currentUser === null) {
    console.log("addMessage requires a signed-in user");
    return;
  }

  const message: ChatMessage = {
    name: this.currentUser.displayName,
    profilePicUrl: this.currentUser.photoURL,
    timestamp: serverTimestamp(),
    uid: this.currentUser?.uid,
  };

  textMessage && (message.text = textMessage);
  imageUrl && (message.imageUrl = imageUrl);

  try {
    const newMessageRef = await addDoc(
      collection(this.firestore, "messages"),
      message,
    );
    return newMessageRef;
  } catch (error) {
    console.error("Error writing new message to Firebase Database", error);
    return;
  }
};

測試傳送訊息

  1. 建立含有修訂訊息「Post new chat to Firestore」的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。
  3. 重新整理 friendlyChat。登入後,請輸入「嘿,你好!」之類的訊息,然後按一下「傳送」。這項操作會將訊息寫入 Cloud Firestore。不過,您無法在實際網頁應用程式中查看資料,因為您仍需實作「擷取資料」(程式碼研究室的下一節)。
  4. 您可以在 Firebase 控制台查看新增的訊息。開啟模擬器套件 UI。在「Build」部分下,按一下「Firestore Database」 (或按一下這裡,應該會看到「messages」集合和新新增的訊息:

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(12) 僅監聽最近 12 則訊息,並使用 orderBy('timestamp', 'desc') 依日期排序訊息,藉此取得 12 則最新訊息。

collectionData 函式會在背景使用快照。如果符合查詢的文件有任何變更,就會觸發回呼函式。如果訊息可能遭到刪除、修改或新增,就可能發生這種情況。詳情請參閱 Cloud Firestore 說明文件

測試同步處理訊息

  1. 建立含有修訂訊息「Show new chat in the UI」的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。
  3. 重新整理 friendlyChat。您先前在資料庫中建立的訊息應該會顯示在 friendlyChat UI 中 (請見下方)。您可以隨意撰寫新訊息,訊息會立即顯示。
  4. (選用) 您可以嘗試直接在 Emulator 套件的「Firestore」部分手動刪除、修改或新增訊息,且任何變更都應反映在使用者介面中。

恭喜!您正在應用程式讀取 Cloud Firestore 文件!

angularfire-2.png

11. 新增 AI 功能

你將使用 Google AI 在即時通訊應用程式中新增實用的輔助功能。

取得 Google AI API 金鑰

  1. 前往 Google AI Studio,然後按一下「Create API key」(建立 API 金鑰)
  2. 選取您為這個程式碼研究室建立的 Firebase 專案。系統提供的提示是關於 Google Cloud 專案,但每項 Firebase 專案都是 Google Cloud 專案。
  3. 按一下「在現有專案中建立 API 金鑰」
  4. 複製產生的 API 金鑰

安裝擴充功能

這項擴充功能會部署一個 Cloud 函式,每當新文件新增至 Firestore 的「messages」集合時就會觸發這個 Cloud 函式。函式會呼叫 Gemini,並將回覆寫回文件的 response 欄位。

  1. 在「使用 Gemini API 建構聊天機器人」擴充功能頁面中,按一下「在 Firebase 控制台安裝」
  2. 請依照系統的提示操作。進入「設定擴充功能」步驟後,請設定下列參數值:
    • Gemini API 供應商:Google AI
    • Google AI API 金鑰:貼上先前建立的金鑰,然後按一下「建立密鑰」
    • Firestore 集合路徑:messages
    • 提示欄位:text
    • 回應欄位:response
    • 訂單欄位:timestamp
    • 背景資訊:Keep your answers short, informal, and helpful. Use emojis when possible.
  3. 按一下安裝擴充功能
  4. 等待擴充功能安裝完成

測試 AI 功能

PersonalizedChat 已有用來讀取 AI 擴充功能回覆的程式碼。只要傳送新的即時通訊訊息就能進行測試!

  1. 開啟 friendlyChat 並傳送訊息。
  2. 稍待片刻,訊息旁邊應會彈出回應。結尾有 ✨ ai generated 的附註,以明確表示訊息是使用生成式 AI 建立,而非真實使用者。

12. 傳送圖片

您現在可以新增分享圖片的功能。

雖然 Cloud Firestore 適合用來儲存結構化資料,Cloud Storage 則更適合用來儲存檔案。Cloud Storage for Firebase 是一項檔案/blob 儲存服務,可用來儲存使用者透過應用程式分享的所有圖片。

將圖片儲存至 Cloud Storage

您已在本程式碼研究室中新增可觸發檔案選擇器對話方塊的按鈕。選取檔案後,系統會呼叫 saveImageMessage 函式,方便您取得所選檔案的參照。saveImageMessage 函式會完成以下作業:

  1. 在聊天室訊息串建立「預留位置」即時通訊訊息,讓使用者在您上傳圖片時會看到「載入中」動畫。
  2. 將圖片檔上傳至 Cloud Storage 至下列路徑:/<uid>/<file_name>
  3. 產生圖片檔的可公開讀取網址。
  4. 使用新上傳圖片檔的網址更新即時通訊訊息,取代暫存載入圖片。

現在,請新增功能來傳送圖片:

  1. 返回 src/chat.service.ts 檔案。
  2. 找出 saveImageMessage 函式。
  3. 使用下列程式碼取代整個函式。

chat.service.ts

// Saves a new message containing an image in Firestore.
// This first saves the image in Firebase storage.
saveImageMessage = async(file: any) => {
  try {
    // 1 - 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. 建立含有修訂訊息「Add theability to 張貼 images」的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。
  3. 重新整理 friendlyChat。登入後,請點選左下角的「圖片上傳」按鈕 angularfire-4.png,然後使用檔案選擇器選取圖片檔。尋找圖片時,不妨使用這張一張不錯咖啡杯圖片
  4. 應用程式的 UI 上應會顯示新訊息,而且有你選取的圖片:angularfire-2.png

如果您在未登入的情況下嘗試新增圖片,應該會看到一則錯誤訊息,要求您登入才能新增圖片。

13. 顯示通知

我們現在將支援瀏覽器通知。有人在即時通訊中發布新訊息時,應用程式會通知使用者。Firebase 雲端通訊 (FCM) 是跨平台的訊息傳遞解決方案,可用來穩定傳送訊息和通知,無須額外付費。

新增 FCM Service Worker

網頁應用程式需要服務工作處理程序,以便接收及顯示網路通知。

新增 AngularFire 時,訊息供應商就應該已設定完畢。請確認 /angularfire-start/src/app/app.module.ts 的「import」部分已有下列程式碼

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

app/app.module.ts

Service Worker 只需載入並初始化 Firebase 雲端通訊 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. 建立含有修訂訊息「Add theability to 張貼 images」的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。
  3. 重新整理 friendlyChat。登入後,畫面上應該會顯示通知權限對話方塊:bd3454e6dbfb6723.png
  4. 按一下「Allow」
  5. 開啟瀏覽器的 JavaScript 控制台。您應該會看到下列訊息:Got FCM device token: cWL6w:APA91bHP...4jDPL_A-wPP06GJp1OuekTaTZI5K2Tu
  6. 複製裝置權杖。在程式碼研究室的下一階段,您會需要用到。

傳送通知到你的裝置

現在有了裝置權杖,您可以傳送通知。

  1. 開啟 Firebase 控制台的「雲端通訊」分頁
  2. 按一下「新通知」
  3. 輸入通知標題和通知文字。
  4. 按一下畫面右側的「傳送測試訊息」
  5. 輸入從瀏覽器 JavaScript 控制台複製的裝置權杖,然後按一下加號 (「+」) 符號
  6. 按一下「測試」

如果應用程式位於前景,JavaScript 控制台中會顯示通知。

如果應用程式在背景執行,瀏覽器應該會顯示通知,如以下範例所示:

de79e8638a45864c.png

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

安全性規則應該會自動更新至 Emulator 套件。

查看 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

您可以使用下列規則導入:

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

15. 恭喜!

您已使用 Firebase 建構即時聊天網頁應用程式!

涵蓋內容

  • Firebase App Hosting
  • Firebase 驗證
  • Cloud Firestore
  • Cloud Storage 專用的 Firebase SDK
  • Firebase 雲端通訊
  • Firebase Performance Monitoring

後續步驟

瞭解詳情

16. [選用] 透過 App Check 強制執行

Firebase App Check 可協助保護服務,避免受到無效流量影響,並避免後端遭到濫用。在這個步驟中,您將透過 App Check 和 reCAPTCHA Enterprise 新增憑證驗證並封鎖未經授權的用戶端。

首先,請啟用 App Check 和 reCAPTCHA。

啟用 reCAPTCHA Enterprise

  1. 在 Cloud 控制台的「安全性」下方,找出並選取「reCAPTCHA Enterprise」
  2. 按照系統提示啟用服務,然後按一下「Create Key」
  3. 按照系統提示輸入顯示名稱,然後選取「網站」做為平台類型。
  4. 將已部署的網址新增至「網域清單」,並確認「使用核取方塊驗證方式」選項未選取
  5. 按一下「建立金鑰」,並將產生的金鑰儲存在其他位置來妥善保存。後續步驟會用到這項資訊。

啟用 App Check

  1. 在 Firebase 控制台中,找到左側面板中的「Build」區段。
  2. 依序按一下「App Check」和「Sign-in method」分頁標籤,前往「App Check」
  3. 按一下 [註冊],並在系統提示時輸入您的 reCAPTCHA Enterprise 金鑰,然後按一下「儲存」
  4. 在 API 檢視畫面中選取「Storage」,然後點選「強制執行」。對 Cloud Firestore 執行相同操作。

系統現在應會強制執行 App Check!請重新整理應用程式,並嘗試查看或傳送即時通訊訊息。您應該會看到下列錯誤訊息:

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

這表示 App Check 預設會封鎖未經驗證的要求。現在,請將驗證新增至應用程式。

前往 environment.ts 檔案,然後將 reCAPTCHAEnterpriseKey 新增至 environment 物件。

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 初始化作業,並將 isTokenAutoRefreshEnabled 設為 true,允許權杖自動重新整理。

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_TOKEN 設為 true。當您在 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 的「應用程式檢視畫面」

按一下溢位選單,然後選取「管理偵錯權杖」

接著,按一下「Add debug token」,按照提示貼上控制台中的偵錯權杖。

前往 chat.service.ts 檔案,並新增下列匯入項目:

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

在同一個 chat.service.ts 檔案中,插入 App Check 與其他 Firebase 服務。

export class ChatService {
appCheck: AppCheck = inject(AppCheck);
...
  1. 建立含有「使用 App Check 封鎖未經授權的用戶端」修訂版本的修訂版本,並推送至 GitHub 存放區。
  2. 在 Firebase 控制台中開啟 App Hosting 頁面,等待新推出作業完成。

恭喜!App Check 現在應該可以在你的應用程式中運作。