Catch up on everthing we announced at this year's Firebase Summit. Learn more

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

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

  • addMessage():提供一个接受文本值的网址,并将文本值写入 Cloud Firestore。
  • makeUppercase():在有数据写入 Cloud Firestore 时触发,并将文本转换为大写。

我们为此示例选择了 Cloud Firestore 和由 HTTP 触发的 JavaScript 函数,部分原因是可以通过 Firebase Local Emulator Suite 对这些后台触发器进行全面测试。此工具集还支持实时数据库、PubSub、Auth 和 HTTP Callable 触发器。其他类型的后台触发器(如 Remote Config、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 Version Manager 安装 Node.js 和 npm

安装 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 工具进行身份验证。
  2. 转到 Firebase 项目目录。
  3. 运行 firebase init firestore。在本教程中,当系统提示您选择 Firestore 规则和索引文件时,您可以接受默认值。如果您尚未在此项目中使用 Cloud Firestore,则还需要按照 Cloud Firestore 使用入门中的说明为 Firestore 选择开始模式和位置。
  4. 运行 firebase init functions。该工具会为您提供使用 npm 安装依赖项的选项。如果您希望通过其他方式管理依赖项,可以放心地拒绝此选项;但如果拒绝,则需要在模拟或部署函数之前运行 npm install
  5. 该工具支持两种语言:

    在本教程中,选择 JavaScript

这些命令成功完成后,您的项目结构应如下所示:

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": "10"}。它指定了用于编写和部署函数的 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 应用实例。与 FCM、Authentication、Firebase Realtime Database 一样,在支持 Admin SDK 的所有环境中,都提供了一种使用 Cloud Functions 来集成 Firebase 的强大方法。

当您初始化项目时,Firebase CLI 会自动安装 Firebase 和 Firebase SDK for Cloud Functions 这两个 Node 模块。如需将第三方库添加到项目中,您可以修改 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 端点。向端点发送的任何请求都会导致将 ExpressJS 样式的 RequestResponse 对象传递给 onRequest() 回调函数。

HTTP 函数是同步函数(类似于 Callable 函数),因此您应该尽快发送响应并使用 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 都会触发 onWrite() 回调函数。

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

模拟函数的执行

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

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

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

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

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

  5. 在模拟器套件界面中查看函数的效果:

    1. 日志标签页中,您应该会看到表示函数 addMessage()makeUppercase() 运行的新日志:

      i 函数:“addMessage”开始执行

      i 函数:“makeUppercase”开始执行

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

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

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

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

    函数就会执行,并将浏览器重定向到 Firebase 控制台中存储着该文本字符串的数据库位置。这一写入事件触发了 makeUppercase(),后者将写入该字符串的大写形式。

部署和执行函数后,您可以在 Firebase 控制台中查看 Cloud Functions 的日志。如果您需要在开发或生产环境中删除函数,请使用 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');

// 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,您还可以执行以下操作:

视频教程

您可以通过观看视频教程来详细了解 Cloud Functions。在此视频中,您将了解有关如何开始使用 Cloud Functions(包括 Node.js 和 CLI 设置)的详细指南。