通常您将需要对您的函数进行额外配置,例如第三方 API 密钥或可调整的设置。Firebase SDK for Cloud Functions 提供了内置环境配置,让您可以轻松为项目存储和检索此类数据。
您可以使用 Firebase CLI 和 functions.config
选择基于文件的环境变量配置(推荐)或运行时环境配置。本指南对这两种方法进行了介绍。
环境变量
Cloud Functions for Firebase 支持使用 dotenv 文件格式将 .env
文件中指定的环境变量加载到应用运行时。部署后,环境变量可通过 process.env
接口读取。
如需以这种方式配置环境,请在项目中创建 .env
文件,添加所需的变量,然后进行部署:
在
functions/
目录中创建一个.env
文件:# Directory layout: # my-project/ # firebase.json # functions/ # .env # package.json # index.js
打开
.env
文件进行修改,然后添加所需的键。例如:PLANET=Earth AUDIENCE=Humans
部署函数并验证是否已加载环境变量:
firebase deploy --only functions # ... # i functions: Loaded environment variables from .env. # ...
部署自定义环境变量后,您的函数代码即可使用 process.env
语法访问这些变量:
// Responds with "Hello Earth and Humans"
exports.hello = functions.https.onRequest((request, response) => {
response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});
部署多组环境变量
如果您的 Firebase 项目需要一组替代的环境变量(例如预演环境变量与生产环境变量),请创建 .env.<project or
alias>
文件并在其中写入项目特定的环境变量。.env
文件和项目专属 .env
文件(如果存在)中的环境变量将包含在所有已部署的函数中。
例如,一个项目可以包含以下三个文件,其中包含的分别用于开发和生产环境的值略有不同:
.env
|
.env.dev
|
.env.prod
|
PLANET=Earth
AUDIENCE=Humans |
AUDIENCE=Dev Humans | AUDIENCE=Prod Humans |
鉴于这些单独文件中的值,随函数部署的环境变量集会因目标项目而异:
$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
# PLANET=Earth
# AUDIENCE=Dev Humans
$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
# PLANET=Earth
# AUDIENCE=Prod Humans
预留的环境变量
某些环境变量键已预留供内部使用。请勿在 .env
文件中使用以下任何键:
- 以 X_GOOGLE_ 开头的所有键
- 以 EXT_ 开头的所有键
- 以 FIREBASE_ 开头的所有键
- 以下列表中的任何键:
- CLOUD_RUNTIME_CONFIG
- ENTRY_POINT
- GCP_PROJECT
- GCLOUD_PROJECT
- GOOGLE_CLOUD_PROJECT
- FUNCTION_TRIGGER_TYPE
- FUNCTION_NAME
- FUNCTION_MEMORY_MB
- FUNCTION_TIMEOUT_SEC
- FUNCTION_IDENTITY
- FUNCTION_REGION
- FUNCTION_TARGET
- FUNCTION_SIGNATURE_TYPE
- K_SERVICE
- K_REVISION
- PORT
- K_CONFIGURATION
存储和访问敏感的配置信息
存储在 .env
文件中的环境变量可用于函数配置,但您不应认为它们是存储数据库凭据或 API 密钥等敏感信息的安全方式。如果您将 .env
文件签入源代码控制系统,这一点尤为重要。
为了帮助您存储敏感的配置信息,Cloud Functions for Firebase 与 Google Cloud Secret Manager 相集成。此加密服务可以安全存储配置值,同时仍可让您在需要时轻松从您的函数进行访问。
创建和使用 Secret
如需创建 Secret,请使用 Firebase CLI。
如需创建和使用 Secret,请执行以下操作:
从本地项目目录的根目录中,运行以下命令:
firebase functions:secrets:set SECRET_NAME
输入 SECRET_NAME 的值。
CLI 会回显成功消息并警告您必须部署函数,以使更改生效。
在部署之前,请确保您的函数代码允许函数使用
runWith
参数访问 Secret:exports.processPayment = functions // Make the secret available to this function .runWith({ secrets: ["SECRET_NAME"] }) .onCall((data, context) => { const myBillingService = initializeBillingService( // reference the secret value process.env.SECRET_NAME ); // Process the payment });
部署 Cloud Functions 函数:
firebase deploy --only functions
现在,您可以像访问任何其他环境变量一样对其进行访问。
相对地,如果另一个没有在 runWith
中指定 Secret 的函数试图访问该 Secret,则会收到一个未定义的值:
exports.anotherEndpoint = functions.https.onRequest((request, response) => {
response.send(`The secret API key is ${process.env.SECRET_NAME}`);
// responds with "The secret API key is undefined" because the `runWith` parameter is missing
});
函数部署后便可访问 Secret 值。只有在其 runWith
参数中明确包含 Secret 的函数才能以环境变量的形式访问该 Secret。这有助于确保 Secret 值仅在需要时才可用,从而降低意外泄露 Secret 的风险。
管理 Secret
使用 Firebase CLI 管理您的 Secret。以这种方式管理 Secret 时,请记住,某些 CLI 更改需要您修改和/或重新部署关联的函数。具体而言:
- 每次为 Secret 设置新值时,您都必须重新部署所有引用该 Secret 的函数,以使它们获取最新值。
- 如果您删除 Secret,请确保已部署的所有函数均未引用该 Secret。使用已删除的 Secret 值的函数将静默失败。
下面总结了用于 Secret 管理的 Firebase CLI 命令:
# Change the value of an existing secret firebase functions:secrets:set SECRET_NAME # View the value of a secret functions:secrets:access SECRET_NAME # Destroy a secret functions:secrets:destroy SECRET_NAME # View all secret versions and their state functions:secrets:get SECRET_NAME # Automatically clean up all secrets that aren't referenced by any of your functions functions:secrets:prune
对于 access
和 destroy
命令,您可以提供可选的版本参数来管理特定版本。例如:
functions:secrets:access SECRET_NAME[@VERSION]
如需详细了解这些操作,请使用命令传递 -h
以查看 CLI 帮助。
Secret 的结算方式
Secret Manager 允许您免费拥有 6 个有效的 Secret 版本。这意味着一个 Firebase 项目每月可以免费拥有 6 个 Secret。
默认情况下,Firebase CLI 会在适当的时候(例如,在使用新版本的 Secret 部署函数时)尝试自动销毁未使用的 Secret 版本。此外,您还可以使用 functions:secrets:destroy
和 functions:secrets:prune
主动清理未使用的 Secret。
Secret Manager 允许每月对一个 Secret 执行 10,000 次未结算的访问操作。函数实例会在每次冷启动时仅读取在其 runWith
参数中指定的 Secret。如果您有许多函数实例读取大量 Secret,则您的项目可能会超出此限额,此时系统会按照每 10,000 次访问操作 $0.03 的费率向您收取费用。
如需了解详情,请参阅 Secret Manager 价格。
模拟器支持
使用 dotenv 的环境配置可与本地 Cloud Functions 模拟器进行互操作。
使用本地 Cloud Functions 模拟器时,您可以通过设置 .env.local
文件来替换项目的环境变量。.env.local
的内容优先于 .env
和项目特定的 .env
文件。
例如,一个项目可以包含以下三个文件,这些文件中包含的用于开发和本地测试的值会略有不同:
.env
|
.env.dev
|
.env.local
|
PLANET=Earth
AUDIENCE=Humans |
AUDIENCE=Dev Humans | AUDIENCE=Local Humans |
在本地环境中启动时,模拟器会加载环境变量,如下所示:
$ firebase emulators:start
i emulators: Starting emulators: functions
# Starts emulator with following environment variables:
# PLANET=Earth
# AUDIENCE=Local Humans
Cloud Functions 模拟器中的 Secret 和凭据
Cloud Functions 模拟器支持使用 Secret 存储和访问敏感配置信息。默认情况下,模拟器将尝试使用应用默认凭据访问生产 Secret。在某些情况(例如 CI 环境)下,模拟器可能会由于权限限制而无法访问 Secret 值。
与 Cloud Functions 模拟器对环境变量的支持类似,您可以通过设置 .secret.local
文件来替换 Secret 值。这样,您就可以轻松地在本地测试函数,尤其是当您无法访问 Secret 值时。
从环境配置迁移
如果您一直将环境配置与 functions.config
搭配使用,则可以将现有配置作为环境变量(采用 dotenv 格式)迁移。Firebase CLI 提供了一条导出命令,用于输出您目录的 .firebaserc
文件中列出的每个别名或项目(下面示例中的 local
、dev
和 prod
)的配置作为 .env
文件。
如需迁移,请使用 firebase functions:config:export
命令导出现有的环境配置:
firebase functions:config:export i Importing configs from projects: [project-0, project-1] ⚠ The following configs keys could not be exported as environment variables: ⚠ project-0 (dev): 1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.) Enter a PREFIX to rename invalid environment variable keys: CONFIG\_ ✔ Wrote functions/.env.prod ✔ Wrote functions/.env.dev ✔ Wrote functions/.env.local ✔ Wrote functions/.env
请注意,在某些情况下,系统会提示您输入前缀以重命名导出的环境变量键。这是因为并非所有配置都可以自动转换,具体原因是它们可能无效或者可能是预留的环境变量键。
我们建议您在部署函数或将 .env
文件签入源代码控制系统之前仔细审核生成的 .env
文件的内容。如果任何值属于敏感信息且不应泄露,请将其从 .env
文件中移除,并改为将其安全地存储在 Secret Manager 中。
您还需要更新函数代码。任何使用 functions.config
的函数现在都需要改用 process.env
,如环境变量中所示。
环境配置
在 firebase-functions
v3.18.0
中开始支持环境变量之前,我们推荐使用 functions.config()
来配置环境。此方法仍受支持,但我们建议所有新项目改用环境变量,因为它们更易于使用并且可以提高代码的可移植性。
使用 CLI 进行环境配置
如需存储环境数据,您可以使用 Firebase CLI 中的 firebase functions:config:set
命令。
每个键都可以使用句点设置命名空间,以便将相关配置组合在一起。请注意,键只能使用小写字符;请勿使用大写字符。
例如,要存储“某些服务”的客户端 ID 和 API 密钥,您可以运行:
firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"
检索当前环境配置
要检查当前存储在项目的环境配置中的内容,您可以使用 firebase functions:config:get
。它会输出如下 JSON:
{
"someservice": {
"key":"THE API KEY",
"id":"THE CLIENT ID"
}
}
此功能基于 Google Cloud Runtime Configuration API。
在函数中使用 functions.config
访问环境配置
系统在预留的 firebase
命名空间下自动提供了部分配置。通过 functions.config()
可在运行的函数内使用环境配置。
要使用上述配置,代码可能如下所示:
const functions = require('firebase-functions');
const request = require('request-promise');
exports.userCreated = functions.database.ref('/users/{id}').onWrite(event => {
let email = event.data.child('email').val();
return request({
url: 'https://someservice.com/api/some/call',
headers: {
'X-Client-ID': functions.config().someservice.id,
'Authorization': `Bearer ${functions.config().someservice.key}`
},
body: {email: email}
});
});
使用环境配置来初始化模块
某些 Node 模块无需任何配置即可使用。其他模块需要额外的配置才能正确初始化。我们建议您将此配置存储在环境配置变量中,而非将其硬编码。这有助于提高代码的可移植性,从而使您可以开放应用的源代码,或在生产版本和预演版本之间轻松切换。
例如,如需使用 Slack Node SDK 模块,您可以这样编写代码:
const functions = require('firebase-functions');
const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(functions.config().slack.url);
在部署之前,请设置 slack.url
环境配置变量:
firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX
其他环境命令
firebase functions:config:unset key1 key2
从配置中移除指定的键firebase functions:config:clone --from <fromProject>
将其他项目的环境克隆到当前活动项目中。
自动填充的环境变量
有一些环境变量会自动填充到函数运行时和本地模拟的函数中,其中包括 Google Cloud 填充的环境变量以及特定于 Firebase 的环境变量:
process.env.FIREBASE_CONFIG
:提供以下 Firebase 项目配置信息:
{
databaseURL: 'https://databaseName.firebaseio.com',
storageBucket: 'projectId.appspot.com',
projectId: 'projectId'
}
当您不带任何参数初始化 Firebase Admin SDK 时,系统会自动应用此配置。如果您使用 JavaScript 编写函数,请按如下所示进行初始化:
const admin = require('firebase-admin');
admin.initializeApp();
如果您使用 TypeScript 编写函数,请按如下所示进行初始化:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import 'firebase-functions';
admin.initializeApp();
如果您需要使用服务帐号凭据以默认项目配置初始化 Admin SDK,则可以从文件加载凭据并将它们添加到 FIREBASE_CONFIG
中,如下所示:
serviceAccount = require('./serviceAccount.json');
const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);