使用入门:编写、测试和部署您的第一批函数


开始使用 Cloud Functions 前,请先完成本教程。您将从必要的设置任务开始,直到完成两个相关函数的创建、测试和部署:

  • “添加消息”函数,用于提供一个接受文本值的网址,并将其写入 Cloud Firestore。
  • “转换为大写”函数,用于在 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 Local Emulator Suite 对这些后台触发器进行全面测试。此工具集还支持 Realtime Database、Cloud Storage、PubSub、Auth 和 HTTP Callable 触发器。其他类型的后台触发器(如 Remote Config 和 TestLab 触发器)可以使用本页面中未介绍的其他工具集进行交互式测试

本教程的以下各部分将详细介绍构建、测试和部署示例所需的步骤。

创建 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 项目的概览页面。

设置您的环境和 Firebase CLI

Node.js

您需要使用 Node.js 环境来编写函数,并且需要使用 Firebase CLI 将函数部署到 Cloud Functions 运行时。建议您使用 Node Version Manager 来安装 Node.js 和 npm

安装 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

初始化您的项目

初始化 Firebase SDK for Cloud Functions 时,您需要创建一个空项目(其中包含依赖项和一些少量的示例代码)。如果您使用的是 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

    在本教程中,选择 JavaScriptPython。如需使用 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 应用实例。与 FCM、Authentication、Firebase Realtime Database 一样,在支持 Admin SDK 的所有环境中,都提供了一种使用 Cloud Functions 来集成 Firebase 的强大方法。

当您初始化项目时,Firebase CLI 会自动安装 Firebase Admin SDK 和 Firebase SDK for Cloud Functions 这两个模块。如需详细了解如何向项目添加第三方库,请参阅处理依赖项

添加“添加消息”函数

如需加入“添加消息”函数,请将以下代码行添加到源代码文件中:

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 函数是同步函数(类似于 Callable 函数),因此您应该尽快发送响应并推迟使用 Cloud Firestore 的工作。“添加消息”HTTP 函数将文本值传递到 HTTP 端点,并将其插入数据库中的 /messages/:documentId/original 路径下。

添加“转换为大写”函数

对于“转换为大写”函数,请将以下代码行添加到源代码文件中:

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


向 Cloud Firestore 写入数据时,系统会执行“转换为大写”函数,定义要监听的文档。考虑到性能原因,定义应尽可能具体。

大括号可用于括住“参数”(例如 {documentId}),即在回调函数中提供其匹配数据的通配符。每当添加了新消息时,Cloud Firestore 都会触发回调函数。

在 Node.js 中,事件驱动型函数(如 Cloud Firestore 事件)是异步的。回调函数应返回 null、一个对象或一个 Promise。如果您不返回任何结果,函数就会超时,示意发生错误,然后重试。请参阅同步、异步和 Promise

模拟函数的执行

借助 Firebase Local Emulator Suite,您可以在本地机器上构建和测试应用,而无需部署到 Firebase 项目。我们强烈建议在开发期间进行本地测试,部分原因是可以降低因代码错误(例如无限循环)而在生产环境中产生费用的风险。

如需模拟函数,请执行以下操作:

  1. 运行 firebase emulators:start 并检查 Emulator Suite 界面的网址输出。它默认为 localhost:4000,但可以托管在您机器的其他端口上。在浏览器中输入该网址,以打开 Emulator Suite 界面。

  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。(可选)您可以将消息“uppercaseme”更改为自定义消息。

  4. 在浏览器的新标签页中打开该网址,创建一条新消息。

  5. 在 Emulator Suite 界面中查看函数的效果:

    1. 日志标签页中,您应该会看到表示 HTTP 函数已成功运行的新日志:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. Firestore 标签页中,您应该会看到包含原始消息及此消息的大写版本(如果最初是“uppercaseme”,则显示“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 函数应指定位置以尽可能缩短网络延迟时间。

    如果遇到访问错误,例如“Unable to authorize access to project”(无法授予项目访问权限),请尝试检查您的项目别名

  2. 使用 CLI 输出的网址,添加文本查询参数,并在浏览器中打开该网址:

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

    函数就会执行,并将浏览器重定向到 Firebase 控制台中存储着该文本字符串的数据库位置。此写入事件会触发“转换为大写”函数,该函数会写入字符串的大写版本。

部署和执行函数后,您可以在 Google Cloud 控制台中查看日志。如果您需要在开发或生产环境中删除函数,请使用 Firebase CLI。

在生产环境中,您可能希望设置要运行的实例数下限和上限,以优化函数性能并控制费用。如需详细了解这些运行时选项,请参阅控制扩缩行为

后续步骤

在此文档中,您可以详细了解如何管理 Cloud Functions 函数,以及如何处理 Cloud Functions 支持的所有事件类型。

如需详细了解 Cloud Functions,您还可以: