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


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

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

以下是包含函式的完整程式碼範例:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

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

initializeApp();

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = 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 getFirestore()
      .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 saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

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

  const uppercase = original.toUpperCase();

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

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()


@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")


@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

關於本教學課程

我們這次為這個範例選擇了 Cloud Firestore 和 HTTP 觸發函式,原因是這些背景觸發條件可以透過 Firebase 本機模擬器套件徹底測試。這個工具集也支援即時資料庫、Cloud Storage、PubSub、驗證和 HTTP 可呼叫觸發條件。您可以使用本頁未提及的工具組以互動方式測試其他類型的背景觸發條件 (例如遠端設定和 TestLab 觸發條件)。

本教學課程的下列各節詳細說明建構、測試及部署範例的必要步驟。

建立 Firebase 專案

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

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

    • 輸入所需專案名稱,即可建立新專案。您也可以視需要編輯專案名稱下方的專案 ID。

  2. 出現提示訊息時,請詳閱並接受《Firebase 條款》。

  3. 點選「繼續」

  4. (選擇性步驟) 為專案設定 Google Analytics (分析),讓您使用下列任一 Firebase 產品享有最佳體驗:

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

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

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

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

設定環境和 Firebase CLI

Node.js

您需要 Node.js 環境才能寫入函式,另外也需要 Firebase CLI 才能將函式部署至 Cloud Functions 執行階段。如要安裝 Node.js 和 npm,建議您使用 Node 版本管理員

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

npm install -g firebase-tools

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

Python

您需要 Python 環境來編寫函式,也需要 Firebase CLI 才能將函式部署至 Cloud Functions 執行階段。建議您使用 venv 區隔依附元件。支援 Python 3.10 和 3.11 版。

安裝 Python 後,請透過您偏好的方法安裝 Firebase CLI

初始化您的專案

當您初始化 Cloud Functions 專用的 Firebase SDK 時,會建立包含依附元件和一些最少程式碼範例的空白專案。如果您使用的是 Node.js,可以選擇 TypeScript 或 JavaScript 來撰寫函式。為配合本教學課程,您還需要初始化 Cloud Firestore。

如要初始化專案:

  1. 執行 firebase login,透過瀏覽器登入並驗證 Firebase CLI。
  2. 前往 Firebase 專案目錄。
  3. 執行 firebase init firestore。 在本教學課程中,您可以在系統提示輸入 Firestore 規則和索引檔案時接受預設值。如果您尚未在這項專案中使用 Cloud Firestore,也必須按照「開始使用 Cloud Firestore」中的說明,選取 Firestore 的啟動模式和位置。
  4. 執行 firebase init functions。 CLI 會提示您選擇現有程式碼集或初始化,並為新程式碼集命名。當您剛開始使用時,在預設位置只使用單一程式碼集就夠了;之後隨著實作的增加,您可以考慮在程式碼集中整理函式
  5. CLI 提供下列語言支援選項:

    • JavaScript
    • TypeScript
    • Python

    在本教學課程中,請選取「JavaScript」或「Python」。如要瞭解如何使用 TypeScript 編寫函式,請參閱「使用 TypeScript 編寫函式」。

  6. CLI 可讓您選擇安裝依附元件。如果您想以其他方式管理依附元件,這就十分安全。

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

Node.js

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

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

Python

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
      |
      +- main.py      # Main source file for your Cloud Functions code
      |
      +- requirements.txt  #  List of the project's modules and packages 
      |
      +- venv/ # Directory where your dependencies are installed

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

完成設定工作後,您可以開啟來源目錄,並按照以下各節所述的方式開始新增程式碼。在這個範例中,您的專案必須匯入 Cloud Functions 和 Admin SDK 模組。在來源檔案中新增下列幾行內容:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

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

initializeApp();

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()

這些程式碼會載入必要模組,並初始化可用於 Cloud Firestore 變更的 admin 應用程式執行個體。在任何 Admin SDK 支援中,其適用於 FCM、驗證與 Firebase 即時資料庫,它提供了使用 Cloud Functions 整合 Firebase 的強大方法。

在初始化專案時,Firebase CLI 會自動安裝 Firebase Admin SDK 和 Cloud Functions 專用 Firebase SDK。如要進一步瞭解如何在專案中新增第三方程式庫,請參閱「處理依附元件」。

新增「新增訊息」函式

如果是「新增訊息」函式,請在來源檔案中加入這幾行程式碼:

Node.js

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = 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 getFirestore()
      .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.`});
});

Python

@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")

「新增訊息」功能為 HTTP 端點。凡是對端點提出的要求,都會導致要求和回應物件傳遞至平台的要求處理常式 (onRequest()on_request)。

HTTP 函式為同步性質 (與可呼叫的函式類似),因此您應盡快傳送回應,並使用 Cloud Firestore 延後工作。「新增訊息」HTTP 函式會將文字值傳遞至 HTTP 端點,並將文字值插入至路徑 /messages/:documentId/original 下的資料庫。

新增「make case」函式

如果是「make case」函式,請在來源檔案中加入以下幾行內容:

Node.js

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

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

  const uppercase = original.toUpperCase();

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

Python

@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

「make case」函式會在 Cloud Firestore 寫入時執行,以定義要監聽的文件。基於效能考量,請盡可能具體說明。

大括號 (例如 {documentId}) 四周是「參數」,可在回呼中公開其相符資料。每當有新訊息時,Cloud Firestore 就會觸發回呼。

在 Node.js 中,事件導向的函式 (例如 Cloud Firestore 事件) 為非同步性質。回呼函式應傳回 null、物件或 Promise。如果您未傳回任何內容,函式就會逾時並表示錯誤,然後重試。請參閱「同步處理、非同步和 Promise」。

模擬函式執行作業

Firebase 本機模擬器套件可讓您在本機電腦上建構及測試應用程式,而不需部署至 Firebase 專案。強烈建議您在開發期間執行本機測試,其中一項原因是這項功能可降低編寫錯誤的風險,避免在實際工作環境中產生成本 (例如無限迴圈)。

如要模擬函式:

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

  2. 檢查 firebase emulators:start 指令的輸出內容,以取得 HTTP 函式的網址。這看起來與 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. 在「記錄檔」分頁中,您應該會看到新的記錄,指出 HTTP 函式已成功執行:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. 在「Firestore」分頁中,您應該會看到一份包含原始訊息的文件,以及訊息的大寫版本 (如果原本的格式為「大寫」,您會看到「UPPERCASEME」)。

將函式部署至實際工作環境

在模擬器中按照預期運作後,您可以繼續在實際工作環境中部署、測試及執行這些函式。請注意,如要在實際工作環境中部署,您的專案必須採用 Blaze 定價方案。請參閱 Cloud Functions 定價一文。

如要完成教學課程,請部署函式並執行函式。

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

     firebase deploy --only functions
     

    執行這個指令後,Firebase CLI 會輸出所有 HTTP 函式端點的網址。終端機中應會顯示類似下列這一行文字:

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

    這個網址包含您的專案 ID 和 HTTP 函式的區域。雖然現在並不需要擔心,但部分實際工作環境 HTTP 函式應指定位置,以盡可能減少網路延遲時間。

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

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

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

    這個函式會在儲存文字字串的資料庫位置執行瀏覽器,並將瀏覽器重新導向至 Firebase 控制台。這個寫入事件會觸發「make 大寫」函式,以寫入字串的大寫版本。

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

在實際工作環境中,建議您設定要執行的執行個體數量下限與上限,藉此最佳化功能效能並控製成本。如要進一步瞭解這些執行階段選項,請參閱「控制資源調度行為」一節。

後續步驟

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

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