了解 2023 年 Google I/O 大会上介绍的 Firebase 亮点。了解详情

開始:編寫、測試和部署您的第一個函數


要開始使用 Cloud Functions,請嘗試完成本教程,該教程從所需的設置任務開始,並通過創建、測試和部署兩個相關函數來完成:

  • 一個“添加消息”函數,它公開一個接受文本值並將其寫入 Cloud Firestore 的 URL。
  • 在 Cloud Firestore 上觸發的“轉換為大寫”函數寫入並將文本轉換為大寫。

我們為此示例選擇了 Cloud Firestore 和 HTTP 觸發的 JavaScript 函數,部分原因是這些後台觸發器可以通過Firebase Local Emulator Suite進行全面測試。該工具集還支持實時數據庫、PubSub、Auth 和 HTTP 可調用觸發器。其他類型的後台觸發器,例如 Remote Config、TestLab 和 Analytics 觸發器,都可以使用本頁未描述的工具集進行交互式測試

本教程的以下部分詳細介紹了構建、測試和部署示例所需的步驟。如果您只想運行代碼並檢查它,請跳轉到查看完整的示例代碼

創建一個 Firebase 項目

  1. Firebase 控制台中,單擊添加項目

    • 要將 Firebase 資源添加到現有Google Cloud 項目,請輸入其項目名稱或從下拉菜單中選擇它。

    • 要創建新項目,請輸入所需的項目名稱。您還可以選擇編輯項目名稱下方顯示的項目 ID。

  2. 如果出現提示,請查看並接受Firebase 條款

  3. 單擊繼續

  4. (可選)為您的項目設置 Google Analytics,這使您能夠在使用以下任何 Firebase 產品時獲得最佳體驗:

    選擇一個現有的Google Analytics 帳戶或創建一個新帳戶。

    如果您創建一個新帳戶,請選擇您的Analytics 報告位置,然後接受您項目的數據共享設置和 Google Analytics 條款。

  5. 點擊Create project (或者Add Firebase ,如果您使用的是現有的 Google Cloud 項目)。

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 ,請重新運行相同的命令。

初始化你的項目

當您初始化 Firebase SDK for Cloud Functions 時,您會創建一個包含依賴項和一些最小示例代碼的空項目,然後您可以選擇 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 版本。您可以選擇其他支持的版本

導入所需模塊並初始化應用程序

完成設置任務後,您可以打開源目錄並開始添加代碼,如以下部分所述。對於此示例,您的項目必須使用 Node 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");

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

這些行加載firebase-functionsfirebase-admin模塊,並初始化一個可以從中進行 Cloud Firestore 更改的admin應用程序實例。只要Admin SDK支持可用,例如 FCM、身份驗證和 Firebase 實時數據庫,它就提供了一種使用 Cloud Functions 集成 Firebase 的強大方法。

當您初始化項目時,Firebase CLI 會自動安裝 Firebase 和 Firebase SDK for Cloud Functions 節點模塊。要將 3rd 方庫添加到您的項目,您可以修改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 。如果您未返回任何內容,則函數超時,發出錯誤信號,然後重試。請參閱同步、異步和承諾

模擬函數的執行

Firebase Local Emulator Suite允許您在本地計算機上構建和測試應用程序,而不是部署到 Firebase 項目。強烈建議在開發期間進行本地測試,部分原因是它降低了編碼錯誤的風險,而編碼錯誤可能會在生產環境中產生成本(例如,無限循環)。

要模擬您的功能:

  1. 運行firebase emulators:start並檢查 Emulator Suite UI 的 URL 的輸出。它默認為localhost:4000 ,但可能託管在您機器上的不同端口上。在瀏覽器中輸入該 URL 以打開 Emulator Suite UI。

  2. 檢查firebase emulators:start命令的輸出以獲取 HTTP 函數addMessage()的 URL。它看起來類似於http://localhost:5001/MY_PROJECT/us-central1/addMessage ,除了:

    1. MY_PROJECT將替換為您的項目 ID。
    2. 本地計算機上的端口可能不同。
  3. 將查詢字符串?text=uppercaseme添加到函數 URL 的末尾。這應該類似於: http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme 。或者,您可以將消息“uppercaseme”更改為自定義消息。

  4. 通過在瀏覽器的新選項卡中打開 URL 來創建新消息。

  5. 在 Emulator Suite UI 中查看函數的效果:

    1. Logs選項卡中,您應該會看到新日誌,表明函數addMessage()makeUppercase()已運行:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. Firestore選項卡中,您應該會看到一個包含原始消息以及消息的大寫版本的文檔(如果它最初是“uppercaseme”,您會看到“UPPERCASEME”)。

將功能部署到生產環境

一旦您的功能在模擬器中按預期運行,您就可以繼續在生產環境中部署、測試和運行它們。請記住,要部署到推薦的 Node.js 14 運行時環境,您的項目必須採用Blaze 定價計劃。請參閱Cloud Functions 定價

要完成本教程,請部署您的函數,然後執行addMessage()以觸發makeUppercase()

  1. 運行此命令以部署您的函數:

     firebase deploy --only functions
     

    運行此命令後,Firebase CLI 會輸出任何 HTTP 函數端點的 URL。在您的終端中,您應該會看到如下一行:

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

    該 URL 包含您的項目 ID 以及 HTTP 功能的區域。雖然您現在不需要擔心,但一些生產 HTTP 函數應該指定一個位置以最小化網絡延遲。

    如果您遇到訪問錯誤,例如“無法授權訪問項目”,請嘗試檢查您的項目別名

  2. 使用 CLI 輸出的addMessage() URL,添加一個文本查詢參數,並在瀏覽器中打開它:

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

    該函數執行並將瀏覽器重定向到存儲文本字符串的數據庫位置的 Firebase 控制台。此寫入事件觸發makeUppercase() ,它寫入字符串的大寫版本。

部署和執行功能後,您可以在Google Cloud Console中查看日誌。如果您需要刪除開發或生產中的函數,請使用 Firebase CLI。

在生產中,您可能希望通過設置要運行的最小和最大實例數來優化函數性能並控製成本。有關這些運行時選項的更多信息,請參閱控制縮放行為

查看完整的示例代碼

這是包含函數addMessage()makeUppercase()的完整functions/index.js 。這些函數允許您將參數傳遞給將值寫入 Cloud Firestore 的 HTTP 端點,然後通過將字符串中的所有字符大寫來轉換它。

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

// 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 的更多信息,您還可以執行以下操作: