開始使用:編寫、測試及部署第一個函式


如要開始使用 Cloud Functions,請試著逐步完成本教學課程。從必要的設定工作開始,然後逐步建立、測試及部署兩個相關函式:

  • 「新增訊息」函式會公開接受文字值的網址,並將值寫入 Cloud Firestore。
  • 在 Cloud Firestore 上觸發的「make 大寫」函式,會將文字寫入大寫,並轉換為大寫。

我們在此範例中選擇了 Cloud Firestore 和 HTTP 觸發的 JavaScript 函式,原因是這些背景觸發條件可以透過 Firebase 本機模擬器套件充分測試。這個工具集也支援即時資料庫、PubSub、Auth 和 HTTP 可呼叫觸發條件。至於其他類型的背景觸發條件 (例如遠端設定、TestLab 和 Analytics (分析) 觸發條件),您可以使用本頁未提及的工具組,以互動方式進行測試

本教學課程的下列各節將詳細說明建構、測試及部署範例所需的步驟。如果您只想執行程式碼並加以檢查,請跳至 查看完整程式碼範例

建立 Firebase 專案

  1. Firebase 控制台,按一下「新增專案」

    • 如要將 Firebase 資源新增至「現有的」Google Cloud 專案,請輸入專案名稱,或是從下拉式選單中選取該專案的名稱。

    • 如要建立新專案,請輸入所需專案名稱。您也可以選擇編輯專案名稱下方顯示的專案 ID。

  2. 如果出現提示訊息,請詳閱並接受 Firebase 條款

  3. 接著點選「繼續」

  4. (選用) 為專案設定 Google Analytics (分析),以便使用下列任一 Firebase 產品,享有最佳體驗:

    您可以選取現有的 Google Analytics (分析) 帳戶或建立新帳戶。

    如要建立新帳戶,請選取 Analytics (分析) 報表位置,然後接受專案的資料共用設定和 Google Analytics (分析) 條款。

  5. 按一下「建立專案」。如果使用現有的 Google Cloud 專案,請按一下「新增 Firebase」

Firebase 會自動為你的 Firebase 專案佈建資源。程序完成後,系統會將您導向 Firebase 控制台中 Firebase 專案的總覽頁面。

設定 Node.js 和 Firebase CLI

您需要 Node.js 環境來寫入函式,而且需要 Firebase CLI 才能將函式部署至 Cloud Functions 執行階段。如要安裝 Node.js 和 npm,建議使用 Node Version Manager

安裝 Node.js 與 npm 後,請透過您偏好的方法安裝 Firebase CLI。如要透過 npm 安裝 CLI,請使用:

npm install -g firebase-tools

這樣就會安裝全球可用的 Firebase 指令。如果指令失敗,您可能需要變更 npm 權限。如要更新至最新版 firebase-tools,請再次執行相同的指令。

初始化您的專案

初始化 Cloud Functions 的 Firebase SDK 時,您會建立一個包含依附元件和最少程式碼範例的空白專案,並選擇用於編寫函式的 TypeScript 或 JavaScript。為達成本教學課程的目的,您也需要初始化 Cloud Firestore。

如要初始化專案:

  1. 執行 firebase login 透過瀏覽器登入並驗證 Firebase CLI。
  2. 前往 Firebase 專案目錄。
  3. 執行 firebase init firestore。 在本教學課程中,您可以在系統提示的 Firestore 規則和索引檔案時接受預設值。如果您尚未在這項專案中使用 Cloud Firestore,請一併選取 Firestore 的啟動模式和位置,如開始使用 Cloud Firestore 一文所述。
  4. 執行 firebase init functions。 CLI 會提示您選擇現有的程式碼集,或初始化並命名新的程式碼集。當您剛開始使用時,只需在預設位置建立一個程式碼集即可;之後隨著實作項目擴展,您可能會想要在程式碼集中整理函式
  5. CLI 提供兩種語言支援選項:

    在本教學課程中,請選取「JavaScript」

  6. CLI 可讓您選擇使用 npm 安裝依附元件。如果想要以其他方式管理依附元件,可以放心拒絕,但若拒絕,則需要在模擬或部署函式之前執行 npm install

成功完成這些指令後,您的專案結構會如下所示:

myproject
 +- .firebaserc    # Hidden file that helps you quickly switch between
 |                 # projects with `firebase use`
 |
 +- firebase.json  # Describes properties for your project
 |
 +- functions/     # Directory containing all your functions code
      |
      +- .eslintrc.json  # Optional file containing rules for JavaScript linting.
      |
      +- package.json  # npm package file describing your Cloud Functions code
      |
      +- index.js      # main source file for your Cloud Functions code
      |
      +- node_modules/ # directory where your dependencies (declared in
                       # package.json) are installed

初始化期間建立的 package.json 檔案包含一個重要鍵:"engines": {"node": "16"}。這會指定用於寫入及部署函式的 Node.js 版本。您可以選取其他支援的版本

匯入必要模組並初始化應用程式

完成設定工作後,您可以開啟來源目錄,並按照以下各節所述開始新增程式碼。在此範例中,您的專案必須透過節點 require 陳述式匯入 Cloud Functions 和 Admin SDK 模組。在 index.js 檔案中加入如下所示的程式碼:

// The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
const functions = require('firebase-functions/v1');

// The Firebase Admin SDK to access Firestore.
const admin = require("firebase-admin");
admin.initializeApp();

這些行會載入 firebase-functionsfirebase-admin 模組,並初始化可變更 Cloud Firestore 的 admin 應用程式執行個體。如果除了 FCM、驗證和 Firebase 即時資料庫也有 Admin SDK 支援,這項服務可讓您使用 Cloud Functions 整合 Firebase。

當您初始化專案時,Firebase CLI 會自動安裝 Cloud Functions 節點模組適用的 Firebase 和 Firebase SDK。如要在專案中新增第三方程式庫,您可以修改 package.json 並執行 npm install。詳情請參閱「處理依附元件」。

新增 addMessage() 函式

針對 addMessage() 函式,請在 index.js 中新增以下幾行內容:

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addMessage = functions.https.onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await admin
    .firestore()
    .collection("messages")
    .add({ original: original });
  // Send back a message that we've successfully written the message
  res.json({ result: `Message with ID: ${writeResult.id} added.` });
});

addMessage() 函式是 HTTP 端點。任何傳送至端點的要求都會導致傳遞至 onRequest() 回呼的 ExpressJS 樣式 RequestResponse 物件。

HTTP 函式會同步 (類似於可呼叫的函式),因此您應盡可能快速傳送回應,並使用 Cloud Firestore 延後工作。addMessage() HTTP 函式會將文字值傳遞至 HTTP 端點,並將其插入至路徑 /messages/:documentId/original 下的資料庫。

新增 makeUppercase() 函式

針對 makeUppercase() 函式,請在 index.js 中新增以下幾行內容:

// Listens for new messages added to /messages/:documentId/original and creates an
// uppercase version of the message to /messages/:documentId/uppercase
exports.makeUppercase = functions.firestore
  .document("/messages/{documentId}")
  .onCreate((snap, context) => {
    // Grab the current value of what was written to Firestore.
    const original = snap.data().original;

    // Access the parameter `{documentId}` with `context.params`
    functions.logger.log("Uppercasing", context.params.documentId, original);

    const uppercase = original.toUpperCase();

    // You must return a Promise when performing asynchronous tasks inside a Functions such as
    // writing to Firestore.
    // Setting an 'uppercase' field in Firestore document returns a Promise.
    return snap.ref.set({ uppercase }, { merge: true });
  });

makeUppercase() 函式會在 Cloud Firestore 寫入時執行。ref.set 函式會定義要監聽的文件。基於效能考量,請盡可能具體說明。

括號 (例如 {documentId}) 位於「參數」周圍,或是會在回呼中公開相符資料的萬用字元。

每當新增訊息時,Cloud Firestore 都會觸發 onCreate() 回呼。

事件導向函式 (例如 Cloud Firestore 事件) 為非同步性質。回呼函式應傳回 null、物件或 Promise。如果您未傳回任何值,函式就會逾時並發出錯誤,然後重試。請參閱同步處理、非同步和 Promise

模擬函式的執行作業

Firebase 本機模擬器套件可讓您在本機電腦上建構及測試應用程式,不必部署至 Firebase 專案。強烈建議您在開發期間在本機測試。部分原因在於,這麼做可以降低編寫錯誤的風險,避免在實際工作環境中產生費用 (例如無限迴圈)。

如要模擬函式:

  1. 執行 firebase emulators:start 並檢查模擬器套件 UI 的網址輸出內容。預設值為 localhost:4000,但可能會託管在機器上的其他通訊埠。在瀏覽器中輸入該網址,即可開啟模擬器套件 UI。

  2. 查看 firebase emulators:start 指令的輸出結果,找出 HTTP 函式 addMessage() 的網址。看起來與 http://localhost:5001/MY_PROJECT/us-central1/addMessage 類似,但以下幾點除外:

    1. 系統會將 MY_PROJECT 替換為您的專案 ID。
    2. 本機電腦上的通訊埠可能不同。
  3. 將查詢字串 ?text=uppercaseme 加到函式網址的結尾。如下所示:http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme。您也可以選擇將「大寫」訊息變更為自訂訊息。

  4. 在瀏覽器中開啟新分頁,建立新的訊息。

  5. 在模擬器套件 UI 中查看函式的效果:

    1. 在「記錄」分頁中,您應該會看見表示 addMessage()makeUppercase() 函式的新記錄已執行:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. 在「Firestore」分頁中,您應該會看到內含原始訊息的文件以及訊息的大寫版本 (如果原始訊息是「大寫」,系統會顯示「UPPERCASEME」)。

將函式部署至正式環境

依需求在模擬器中運作函式後,即可繼續在實際工作環境中部署、測試及執行函式。請注意,如要部署至建議的 Node.js 14 執行階段環境,您的專案必須採用 Blaze 定價方案。請參閱 Cloud Functions 定價

如要完成本教學課程,請部署函式,然後執行 addMessage() 來觸發 makeUppercase()

  1. 執行下列指令來部署函式:

     firebase deploy --only functions
     

    執行這個指令之後,Firebase CLI 會輸出任何 HTTP 函式端點的網址。終端機中應該會顯示類似下方的行:

    Function URL (addMessage): https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage
    

    該網址包含您的專案 ID 和 HTTP 函式的區域。雖然您現在不需要擔心,但一些實際工作環境 HTTP 函式應指定位置,以縮短網路延遲時間。

    如果發生存取錯誤 (例如「無法授權存取專案」),請嘗試檢查您的專案別名

  2. 使用 CLI 的 addMessage() 網址輸出,新增文字查詢參數,並在瀏覽器中開啟:

    https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage?text=uppercasemetoo
    

    函式會執行,並將瀏覽器重新導向至儲存文字字串的資料庫位置中的 Firebase 控制台。這個寫入事件會觸發 makeUppercase(),進而寫入字串的大寫版本。

部署及執行函式之後,您可以在 Google Cloud 控制台中查看記錄檔。如果您需要在開發或實際工作環境中刪除函式,請使用 Firebase CLI。

在實際工作環境中,您可以設定要執行的執行個體數量下限與上限,藉此最佳化函式效能並控管費用。如要進一步瞭解這些執行階段選項,請參閱控管資源調度行為

查看完整程式碼範例

以下是包含 addMessage()makeUppercase() 函式的已完成 functions/index.js。這些函式可讓您將參數傳送至 HTTP 端點,此端點會將值寫入 Cloud Firestore,然後以大寫取代字串中的所有字元來轉換。

// The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
const functions = require('firebase-functions/v1');

// The Firebase Admin SDK to access Firestore.
const admin = require("firebase-admin");
admin.initializeApp();

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addMessage = functions.https.onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await admin
    .firestore()
    .collection("messages")
    .add({ original: original });
  // Send back a message that we've successfully written the message
  res.json({ result: `Message with ID: ${writeResult.id} added.` });
});

// Listens for new messages added to /messages/:documentId/original and creates an
// uppercase version of the message to /messages/:documentId/uppercase
exports.makeUppercase = functions.firestore
  .document("/messages/{documentId}")
  .onCreate((snap, context) => {
    // Grab the current value of what was written to Firestore.
    const original = snap.data().original;

    // Access the parameter `{documentId}` with `context.params`
    functions.logger.log("Uppercasing", context.params.documentId, original);

    const uppercase = original.toUpperCase();

    // You must return a Promise when performing asynchronous tasks inside a Functions such as
    // writing to Firestore.
    // Setting an 'uppercase' field in Firestore document returns a Promise.
    return snap.ref.set({ uppercase }, { merge: true });
  });

後續步驟

在本說明文件中,您可進一步瞭解如何為 Cloud Functions 管理函式,以及如何處理 Cloud Functions 支援的所有事件類型。

如要進一步瞭解 Cloud Functions,您也可以執行下列操作: