Firebase Extensions 服务已弃用,并将于 2027 年 3 月 31 日关停。虽然已安装的扩展程序将无限期执行,但在此日期之后,关键管理功能将不再可用。 我们将在 2026 年 9 月发布更多迁移指南和工具。
弃用概览
我们为何要弃用 Firebase Extensions?
由于底层Google Cloud基础架构即将发生变化和弃用,我们将停用托管式Firebase Extensions服务。
2027 年 3 月 31 日之后,已部署的现有扩展程序是否会停止运行?
否。已部署的扩展程序直接在标准 Google Cloud 基础架构(例如 Cloud Functions、Eventarc、Cloud Run 和 Cloud Tasks)上运行,并将无限期继续执行。
不过,在 2027 年 3 月 31 日之后,您将无法再通过 Firebase 控制台或 CLI 更新、重新配置或卸载这些扩展程序。您也将无法再下载现有的扩展程序配置,这会影响您迁移到函数套件。我们强烈建议您在 2027 年 3 月 31 日之前迁移或导出扩展程序配置。
如果用户不采取任何行动,会发生什么情况?
如果用户不采取任何行动,其现有的已部署函数将继续作为标准资源运行。不过,在 2027 年 3 月 31 日之后:
- 他们无法更改配置参数或更新环境变量。
- 它们无法应用 bug 修复、安全补丁或依赖项升级。
- 他们无法下载扩展程序配置,以帮助完全相同地配置替换功能套件。
- 大多数扩展程序目前都是基于旧版 Cloud Functions v1 SDK 构建的,该 SDK 与旧版 Node.js 运行时相关联。一旦 Google Cloud 完全停用这些旧版运行时,函数可能会停止运行或被停用。请参阅运行时支持。
是否有任何产品会取代 Firebase Extensions?
我们已为 Cloud Functions 添加了许多功能,使其能够取代扩展程序。最值得一提的是函数套件,该套件可使用 npm 进行分发,并允许您部署多个函数实例,类似于您可以在单个项目中多次安装扩展程序。
不过,每个扩展程序发布者都可以自行决定是否要在 npm 上发布官方函数套件替代项。由于扩展程序是开源的,因此如果发布商不想制作官方替代方案,任何开发者都可以派生该扩展程序,使用 Node SDK 中的第 2 代 API 制作非官方替代方案。Cloud Functions
如果发布商希望进行替换,应遵循发布商迁移指南中的说明。
如果用户想要利用官方替换软件包或创建自己的替换软件包,可以按照用户迁移指南中的说明操作。
作为扩展程序用户,我应该怎么做?
如果您是扩展程序用户,但不再使用已安装的扩展程序,请在 2027 年 3 月 31 日之前卸载这些扩展程序。
停用后,Firebase 控制台中的“卸载”按钮和相应的 CLI 命令将被移除。您必须使用 Google Cloud 控制台手动删除所有关联的 Google Cloud 资源,包括各个 Cloud Functions、Secret Manager Secret、Cloud Tasks 队列和自定义 IAM 服务账号。
不过,如果您经常使用已安装的扩展程序,我们强烈建议您迁移到功能套件。如需迁移至函数套件,请按照我们的用户迁移指南中的说明操作。
您可以选择不迁移到功能套件,但我们强烈建议您更新所有扩展程序,使其保持最新状态,并导出现有扩展程序配置,以防日后想要迁移。
作为扩展程序发布商,我应该怎么做?
我们建议您将已发布的扩展程序迁移到 npm 上发布的函数套件。您可以先将扩展程序迁移到第 2 代函数,这是创建函数套件的前提条件。这需要使用 Cloud Functions v2 SDK 封装扩展程序逻辑。我们已更新 Cloud Functions v2 SDK,以支持声明式安全和生命周期事件等功能。现在,您可以将现有的扩展代码迁移到第 2 代函数,只需对核心业务逻辑进行极少的更改。这些函数可以使用 npm 软件包发布。如需了解详情,请参阅我们的发布商迁移指南。
如果我还有其他问题,该怎么办?
如有疑问,用户可以参阅我们的用户迁移指南。如果您在使用本指南后仍有疑问,可以与 Firebase 支持团队联系。
如果发布商对如何迁移 Firebase Extensions 有疑问,可以参阅我们的发布商迁移指南。本指南包含相关说明,可帮助您及时了解更新,并获得有关为已发布的扩展程序提供替代方案的帮助。
迁移选项和技术执行
有哪些主要的迁移途径?
自 2026 年 9 月起,Firebase 正式支持两种主要迁移途径:
- 迁移到 NPM 共享函数(“函数套件”):建议用于将 Firestore 流式传输到 BigQuery,以及任何其他在 npm 上提供的函数套件。核心逻辑使用 Cloud Functions v2 SDK 打包为标准 NPM 库。用户初始化标准 Cloud Functions 代码库,安装软件包,重新导出函数,然后使用 CLI 独立部署这些函数。
- Fork 并自行管理:建议所有在 npm 上没有可用功能套件的扩展程序使用此选项。用户复制或派生开源扩展程序源代码,使用尽力而为的 AI 迁移技能或手动指南将触发器重构为标准 Firebase v2 函数,并完全掌控代码库及其持续维护。
哪些扩展程序正在迁移到函数套件?
将 Firestore 流式传输到 BigQuery 扩展程序已迁移到函数套件,该套件以 npm 软件包 @firebase-function-kits/firestore-bigquery-export 的形式提供。
为什么迁移需要从 Cloud Functions v1 升级到 v2?
Cloud Functions v1 标准支持服务将于 Node.js 22 运行时结束。为了防止开发者在迁移到 Firebase Extensions 后,又因旧版运行时停用而被迫进行第二次手动重构,Firebase 强烈建议在此过渡期间立即将所有已迁移的函数升级到 v2 SDK,并且函数套件必须这样做。
作为扩展程序用户,您还可以按照用户迁移指南创建自己的函数套件。
结算和价格
迁移到自行管理的 Cloud Functions 会改变客户的结算方式吗?
一般情况下,不需要。已部署的扩展程序已向客户收取其所消耗的底层 Google Cloud 资源(例如 Cloud Functions 调用、Cloud Storage 或 BigQuery 存储空间和查询)的费用。不过,在迁移窗口期间,如果客户同时运行旧版 Firebase Extensions 和新部署的替代函数,以确保安全割接,则可能会产生少量临时额外费用。
Mandiant 或其他专业企业账号的结算方式是怎样的?
此弃用是一项平台级变更,会影响所有 Firebase 和 Google Cloud 项目。标准结算和订阅安排不受影响。如果客户因弃用停机时间而申请 SLA 抵用金,或者遇到复杂的结算例外情况,请直接通过常规结算支持渠道上报支持请求。
问题排查和风险缓解
迁移期间发生数据丢失或服务停机的风险有多大?
将受管理的资源过渡到自行管理的代码库存在服务中断或事件丢失的轻微风险。
- 触发中断:如果在新触发器处于有效状态之前删除旧触发器,则会产生一个缺口,导致事件(例如 Cloud Firestore 文档写入)丢失且无法恢复。我们建议您先部署替换套件并进行验证,然后再移除扩展程序,以免丢失任何数据。
- 权限缺口:如果新部署的代码库缺少必要的 IAM 权限,则写入 BigQuery 等操作会在运行时静默失败或崩溃。我们为函数添加了声明性安全性,因此,能够查询和设置角色并生成服务账号的账号首次部署套件时,应该可以缓解此问题。
如何防止关键的 Cloud Firestore-to-BigQuery 导出扩展程序发生数据丢失?
为了实现安全且零数据丢失的过渡,支持人员必须建议用户采用基于重叠的切换,而不是基于间隙的切换。这是迁移到套件后的默认行为:
- 在扩展程序仍处于安装和运行状态时,部署替换函数套件。等待几分钟,让 Eventarc 完成全面预配。
- 向受监控的 Cloud Firestore 集合写入测试文档,并验证新的自管理函数是否成功将相应的行(包含新的事件 ID)写入 BigQuery 变更日志表。
- 确认新部署正常运行后,立即卸载或停用旧版扩展程序,以终止双重写入行为。
- 尽可能缩短重叠窗口,以最大限度地减少每次写入的重复处理成本,并降低原始 BigQuery 更改日志中出现重复行的可能性。
- 在大多数情况下,原始变更日志表 (
*_raw_changelog) 将按insertID进行重复数据删除,即使在变更日志中出现重复行的情况下,表的最新视图 (*_raw_latest) 也是正确的。
如需详细了解如何迁移此扩展程序以及如何从任何数据丢失中恢复,请参阅套件的 README.md。
如果生命周期配置步骤失败,该怎么办?
在托管式服务下,设置任务(例如创建 BigQuery 数据集、表和视图)会自动处理。在自管理的 NPM 模型下,这些触发器使用生命周期任务队列函数触发;例如,在 firestore-bigquery-export 中,该函数称为 initBigQuerySync。
如果此步骤失败或未自动运行,请执行以下操作:
验证是否已向 Cloud Functions 运行时服务账号授予所需的 IAM 角色。例如,对于
firestore-bigquery-export,这包括:- 创建资源并插入行:
roles/bigquery.dataEditor - 如需运行作业和构建视图,请执行以下操作:
roles/bigquery.user - 如需将预配任务加入队列,请执行以下操作:
roles/cloudtasks.enqueuer
- 创建资源并插入行:
确认调用者拥有
roles/cloudtasks.enqueuer权限。使用 CLI 手动重新运行生命周期初始化命令:
firebase functions:lifecycle:run afterInstall KIT_INSTANCE_ID检查触发器函数和任务队列执行的 Cloud Logging 日志,以诊断任何权限或配置错误。
Secret Manager 凭据如何迁移?
在受管模型下,Secret Manager 资源会自动绑定到扩展实例。当您使用 ext:migrate 或 ext:export
--mode functions 命令将扩展程序配置导出到函数套件时,我们会停止扩展程序管理这些 Secret,以便在卸载扩展程序后,这些 Secret 仍保留在您的项目中。如果您日后想移除这些密钥,必须在 Google Cloud 控制台中手动执行此操作。
如果用户想要运行迁移后的扩展程序的多个实例,该怎么办?
我们引入了函数套件,以支持函数的多个实例,类似于扩展程序的多个版本。每个软件包都将获得一个唯一的软件包实例 ID,该 ID 类似于代码库,可以在 CLI 命令中与代码库互换使用。部署后,套件实例中的所有函数都将以 kit-<instance-id>- 为前缀,以确保每个函数都有一个唯一的名称,类似于扩展程序中的 ext-<extension-instance-id>- 前缀。如需详细了解如何使用函数套件进行迁移,请参阅我们的用户迁移指南。
Kit 安装使用 npm;如果我想使用 Yarn 或其他 Node 兼容的软件包管理器,该怎么办?
我们目前没有计划支持 Yarn 或其他软件包管理系统。在首次安装时设置套件源代码时,套件安装通过直接执行 npm 命令来完成。
或者,您也可以创建源目录,自行安装该套件 npm 软件包,并使用适当的 build 和导出进行设置。您可以参考
中的 TypeScript index-kit 模板firebase-tools
,也可以查看通过 npm 安装的套件作为示例。完成此操作后,您可以使用 --directory(而非 --package)像安装本地套件一样安装该套件。今后,您需要按目录或 ID 识别功能包,但可以使用功能包命令添加和移除实例。
我的扩展程序使用 Docker 代码库或 KMS 密钥高级系统参数;如何在函数套件中配置这些参数?
目前,我们不支持在 Cloud Functions 中为 Firebase 配置 Docker 代码库或 KMS 密钥。如果您要从配置了这些系统参数的扩展程序迁移,并希望保留此功能,可以使用 gcloud CLI 将这些参数应用于新套件的函数。
前提条件
- 最初,请按照迁移指南部署函数套件,以便函数存在于 Google Cloud 中。
在终端中定义环境变量:
export PROJECT_ID="YOUR_PROJECT_ID" export FUNCTION_REGION="YOUR_REGION" # e.g. us-east1 export KIT_NAME="YOUR_KIT_NAME" # e.g. firestore-bigquery-export export SOURCE_DIR="YOUR_KIT_SOURCE_DIR" # e.g. "./function-kits/${KIT_NAME}/source" export REPO_NAME="YOUR_DOCKER_REPO_NAME" export KEY_RING="YOUR_KMS_KEY_RING" export KEY_NAME="YOUR_KMS_KEY_NAME" # Retrieve Project Number automatically export PROJECT_NUMBER=$(gcloud projects describe "$PROJECT_ID" --format="value(projectNumber)")在 kit 的源代码根目录中预先创建
.gcloudignore,这样.gitignore就不会忽略已编译的 build 文件:cat << 'EOF' > "${SOURCE_DIR}/.gcloudignore" .gcloudignore .git .gitignore node_modules #!include:.gitignore !lib/** EOF授予所需的 IAM 权限:
对于 KMS 密钥(向服务代理授予解密访问权限):
for SERVICE_ACCOUNT in \ "service-${PROJECT_NUMBER}@serverless-robot-prod.iam.gserviceaccount.com" \ "service-${PROJECT_NUMBER}@gcf-admin-robot.iam.gserviceaccount.com" \ "service-${PROJECT_NUMBER}@gcp-sa-artifactregistry.iam.gserviceaccount.com" do gcloud kms keys add-iam-policy-binding "$KEY_NAME" \ --keyring="$KEY_RING" \ --location="$FUNCTION_REGION" \ --project="$PROJECT_ID" \ --member="serviceAccount:${SERVICE_ACCOUNT}" \ --role="roles/cloudkms.cryptoKeyEncrypterDecrypter" done对于 Artifact Registry(授予对 Cloud Build 的写入权限和对 Cloud Run 的读取权限):
# Grant the Cloud Build / Compute Service Account permission to write images to the repository gcloud artifacts repositories add-iam-policy-binding "$REPO_NAME" \ --location="$FUNCTION_REGION" \ --project="$PROJECT_ID" \ --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \ --role="roles/artifactregistry.writer" # Grant Cloud Run permission to pull images from the repository gcloud artifacts repositories add-iam-policy-binding "$REPO_NAME" \ --location="$FUNCTION_REGION" \ --project="$PROJECT_ID" \ --member="serviceAccount:service-${PROJECT_NUMBER}@serverless-robot-prod.iam.gserviceaccount.com" \ --role="roles/artifactregistry.reader"
使用 gcloud CLI 应用设置
针对套件中的每个函数运行 gcloud functions deploy:
gcloud functions deploy FUNCTION_NAME \
--project="$PROJECT_ID" \
--region="$FUNCTION_REGION" \
--source="./function-kits/${KIT_NAME}/source" \
--docker-repository="projects/${PROJECT_ID}/locations/${FUNCTION_REGION}/repositories/${REPO_NAME}" \
--kms-key="projects/${PROJECT_ID}/locations/${FUNCTION_REGION}/keyRings/${KEY_RING}/cryptoKeys/${KEY_NAME}"
请注意,此解决方法在以下情况下会失效:
- 新的套件实例:在
firebase.json中添加实例会创建一个新的 Cloud Functions v2 资源,该资源默认使用 Google 管理的密钥和gcf-artifacts。您必须为每个新实例运行gcloud。 - 函数重新创建:更改触发器类型(例如,从 HTTPS 更改为 Cloud Firestore 触发器)、更改入口点或重命名会导致 Firebase CLI 删除旧函数并创建一个新函数。在您再次运行
gcloud之前,新函数会丢失这些设置。 - 配置漂移:Firebase CLI 不会在
firebase functions:list或 diff 日志中显示 KMS 或 Docker 代码库状态,这使得基础架构审核变得困难。
验证成功
如需确认已应用代码库和加密密钥,请运行以下命令:
gcloud functions describe FUNCTION_NAME \
--region="$FUNCTION_REGION" \
--project="$PROJECT_ID" \
--format="yaml(state, buildConfig.dockerRepository, kmsKeyName)"