您通常需要為函式進行額外設定,例如第三方 API 金鑰或可調整的設定。Cloud Functions 的 Firebase SDK 提供內建環境設定,可讓您輕鬆儲存及擷取專案的這類資料。
你可以選擇下列其中一個選項:
- 參數化設定 (建議用於大多數情境)。這可提供強型別環境設定,並在部署時驗證參數,避免發生錯誤並簡化偵錯作業。
- 環境變數的檔案式設定。採用這種方法時,您必須手動建立 dotenv 檔案,用於載入環境變數。
在多數情況下,建議使用參數化設定。這種方法可讓設定值在執行階段和部署階段都可用,而且除非所有參數都有有效值,否則部署作業會遭到封鎖。相反地,部署時無法使用環境變數進行設定。
參數化設定
Cloud Functions for Firebase 提供介面,可讓您在程式碼集中以宣告方式定義設定參數。在函式部署期間 (設定部署和執行階段選項時) 和執行期間,都可以使用這些參數的值。這表示除非所有參數都有有效值,否則 CLI 會封鎖部署作業。
Node.js
const { onRequest } = require('firebase-functions/v2/https');
const { defineInt, defineString } = require('firebase-functions/params');
// Define some parameters
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
const welcomeMessage = defineString('WELCOME_MESSAGE');
// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
{ minInstances: minInstancesConfig },
(req, res) => {
res.send(`${welcomeMessage.value()}! I am a function.`);
}
);
Python
from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam
MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")
# To use configured parameters inside the config for a function, provide them
# directly. To use them at runtime, call .value() on them.
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')
部署含有參數化設定變數的函式時,Firebase CLI 會先嘗試從本機 .env 檔案載入變數值。如果這些檔案中沒有這些值,且未設定 default,CLI 會在部署期間提示輸入值,然後自動將值儲存到 functions/ 目錄中名為 .env.<project_ID> 的 .env 檔案:
$ firebase deploy
i functions: preparing codebase default for deployment
? Enter a string value for ENVIRONMENT: prod
i functions: Writing new parameter values to disk: .env.projectId
…
$ firebase deploy
i functions: Loaded environment variables from .env.projectId
視開發工作流程而定,建議您將產生的 .env.<project_ID> 檔案新增至版本管控。
在全域範圍使用參數
部署期間,系統會先載入並檢查函式程式碼,再為參數指派實際值。這表示在全域範圍內擷取參數值會導致部署失敗。如要使用參數初始化全域值,請使用初始化回呼 onInit()。這個回呼會在任何函式在正式環境中執行之前執行,但不會在部署期間呼叫,因此可以安全地存取參數值。
Node.js
const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v2/core');
const apiKey = defineSecret('GOOGLE_API_KEY');
let genAI;
onInit(() => {
genAI = new GoogleGenerativeAI(apiKey.value());
})
Python
from firebase_functions.core import init
from firebase_functions.params import StringParam, PROJECT_ID
import firebase_admin
import vertexai
location = StringParam("LOCATION")
x = "hello"
@init
def initialize():
# Note: to write back to a global, you'll need to use the "global" keyword
# to avoid creating a new local with the same name.
global x
x = "world"
firebase_admin.initialize_app()
vertexai.init(PROJECT_ID.value, location.value)
如果使用 Secret 類型的參數,請注意,這些參數只能在已繫結 Secret 的函式程序中使用。如果密鑰只繫結至部分函式,請先確認 secret.value() 是否為 falsy,再使用該密鑰。
設定 CLI 行為
您可以使用 Options 物件設定參數,控制 CLI 提示輸入值的方式。以下範例設定了驗證電話號碼格式、提供簡單選項,以及自動從 Firebase 專案填入選項的選項:
Node.js
const { defineString } = require('firebase-functions/params');
const welcomeMessage = defineString('WELCOME_MESSAGE', {default: 'Hello World',
description: 'The greeting that is returned to the caller of this function'});
const onlyPhoneNumbers = defineString('PHONE_NUMBER', {
input: {
text: {
validationRegex: /\d{3}-\d{3}-\d{4}/,
validationErrorMessage: "Please enter
a phone number in the format XXX-YYY-ZZZZ"
},
},
});
const selectedOption = defineString('PARITY', {input: params.select(["odd", "even"])});
const memory = defineInt("MEMORY", {
description: "How much memory do you need?",
input: params.select({ "micro": 256, "chonky": 2048 }),
});
const extensions = defineList("EXTENSIONS", {
description: "Which file types should be processed?",
input: params.multiSelect(["jpg", "tiff", "png", "webp"]),
});
const storageBucket = defineString('BUCKET', {
description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets",
input: params.PICK_STORAGE_BUCKET,
});
Python
from firebase_functions.params import (
StringParam,
ListParam,
TextInput,
SelectInput,
SelectOptions,
ResourceInput,
ResourceType,
)
MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam(
"WELCOME_MESSAGE",
default="Hello World",
description="The greeting that is returned to the caller of this function",
)
ONLY_PHONE_NUMBERS = StringParam(
"PHONE_NUMBER",
input=TextInput(
validation_regex="\d{3}-\d{3}-\d{4}",
validation_error_message="Please enter a phone number in the format XXX-YYY-XXX",
),
)
SELECT_OPTION = StringParam(
"PARITY",
input=SelectInput([SelectOptions(value="odd"), SelectOptions(value="even")]),
)
STORAGE_BUCKET = StringParam(
"BUCKET",
input=ResourceInput(type=ResourceType.STORAGE_BUCKET),
description="This will automatically populate the selector field with the deploying Cloud Project's storage buckets",
)
參數類型
參數化設定可為參數值提供強型別,也支援 Cloud Secret Manager 的密鑰。支援的類型包括:
- Secret
- 字串
- 布林值
- 整數
- 浮點值
- 清單 (Node.js)
- JSON Secret (Node.js)
如要瞭解定義參數的函式,請參閱 params 命名空間參考資料。
參數值和運算式
Firebase 會在部署和函式執行期間評估參數。由於存在這兩種環境,因此在比較參數值,以及使用參數值設定函式的執行階段選項時,必須特別小心。
如要將參數做為執行階段選項傳遞至函式,請直接傳遞:
Node.js
const { onRequest } = require('firebase-functions/v2/https');
const { defineInt } = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
export const helloWorld = onRequest(
{ minInstances: minInstancesConfig },
(req, res) => {
//…
Python
from firebase_functions import https_fn
from firebase_functions.params import IntParam
MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
...
此外,如果您需要與參數進行比較,才能知道要選擇哪個選項,則需要使用內建的比較器,而不是檢查值:
Node.js
const { onRequest } = require('firebase-functions/v2/https');
const environment = params.defineString(‘ENVIRONMENT’, {default: 'dev'});
// use built-in comparators
const minInstancesConfig = environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = onRequest(
{ minInstances: minInstancesConfig },
(req, res) => {
//…
Python
from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam
ENVIRONMENT = StringParam("ENVIRONMENT", default="dev")
MIN_INSTANCES = ENVIRONMENT.equals("PRODUCTION").then(10, 0)
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
...
如要存取僅在執行階段使用的參數和參數運算式,可以使用 value 函式:
Node.js
const { onRequest } = require('firebase-functions/v2/https');
const { defineString } = require('firebase-functions/params');
const welcomeMessage = defineString('WELCOME_MESSAGE');
// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
(req, res) => {
res.send(`${welcomeMessage.value()}! I am a function.`);
}
);
Python
from firebase_functions import https_fn
from firebase_functions.params import StringParam
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")
@https_fn.on_request()
def hello_world(req):
return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')
內建參數
Cloud Functions SDK 提供三個預先定義的參數,可從 firebase-functions/params 子套件取得:
Node.js
projectID:執行函式的雲端專案。databaseURL:與函式相關聯的即時資料庫執行個體網址 (如果在 Firebase 專案中啟用)。storageBucket:與函式相關聯的 Cloud Storage bucket (如果在 Firebase 專案中啟用)。
Python
PROJECT_ID:執行函式的雲端專案。DATABASE_URL:與函式相關聯的即時資料庫執行個體網址 (如果在 Firebase 專案中啟用)。STORAGE_BUCKET:與函式相關聯的 Cloud Storage bucket (如果在 Firebase 專案中啟用)。
這些函式的運作方式與使用者定義的字串參數完全相同,但由於 Firebase CLI 一律知道其值,因此在部署時不會提示輸入值,也不會儲存至 .env 檔案。
密鑰參數
使用 defineSecret() 定義的 Secret 類型參數,代表值儲存在 Cloud Secret Manager 中的字串參數。密鑰參數不會檢查本機 .env 檔案,並在缺少時將新值寫入檔案,而是會檢查 Cloud Secret Manager 中是否存在密鑰,並在部署期間以互動方式提示輸入新密鑰的值。
Secret 參數必須繫結至應有權存取這些參數的個別函式:
Node.js
const { onRequest } = require('firebase-functions/v2/https');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');
export const postToDiscord = onRequest(
{ secrets: [discordApiKey] },
(req, res) => {
const apiKey = discordApiKey.value();
//…
Python
from firebase_functions import https_fn
from firebase_functions.params import SecretParam
DISCORD_API_KEY = SecretParam('DISCORD_API_KEY')
@https_fn.on_request(secrets=[DISCORD_API_KEY])
def post_to_discord(req):
api_key = DISCORD_API_KEY.value
在函式執行前,密鑰的值會隱藏,因此您無法在設定函式時使用這些值。
結構化 JSON 密鑰
如果您有多個邏輯相關的設定值 (例如第三方服務的設定),可以使用 defineJsonSecret() 將這些值儲存在單一密鑰中,做為結構化 JSON 物件。這種做法可協助您整理設定,並將一組相關設定值儲存在單一 Secret 中,更有效率地使用 Cloud Secret Manager 免費方案。
儲存在 Secret Manager 中的值必須是有效的 JSON 字串。當您存取 .value() 時,SDK 會自動將 JSON 字串剖析為 JavaScript 物件。
範例:
const { onRequest } = require('firebase-functions/v2/https');
const { defineJsonSecret } = require('firebase-functions/params');
// Define a single secret to hold all configuration for some API
const someApiConfig = defineJsonSecret('SOMEAPI_CONFIG');
exports.myApi = onRequest(
{ secrets: [someApiConfig] },
(req, res) => {
// someApiConfig.value() automatically parses the JSON secret
const { apiKey, webhookSecret, clientId } = someApiConfig.value();
// Now you can use apiKey, webhookSecret, clientId
// ...
}
);
如要建立 SOMEAPI_CONFIG 密鑰,請在 Secret Manager 中將其值設為 JSON 字串,例如:
{
"apiKey": "key_...",
"webhookSecret": "secret_...",
"clientId": "client_..."
}
如果密鑰值不是有效的 JSON,存取 someApiConfig.value() 時,系統會在執行階段擲回錯誤。
環境變數
Cloud Functions for Firebase 支援 dotenv 檔案格式,可將 .env 檔案中指定的環境變數載入應用程式執行階段。部署完成後,您可以透過 process.env 介面 (在以 Node.js 為基礎的專案中) 或 os.environ (在以 Python 為基礎的專案中) 讀取環境變數。
如要透過這種方式設定環境,請在專案中建立 .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. # ...
部署自訂環境變數後,函式程式碼就能存取這些變數:
Node.js
// Responds with "Hello Earth and Humans"
exports.hello = onRequest((request, response) => {
response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});
Python
import os
@https_fn.on_request()
def hello(req):
return https_fn.Response(
f"Hello {os.environ.get('PLANET')} and {os.environ.get('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,請使用 Firebase CLI。
如要建立及使用密鑰,請按照下列步驟操作:
在本機專案目錄的根目錄中,執行下列指令:
firebase functions:secrets:set SECRET_NAME
輸入「SECRET_NAME」的值。
CLI 會顯示成功訊息,並警告您必須部署函式,變更才會生效。
部署前,請確認函式程式碼允許函式使用
secrets選項存取 Secret:Node.js
const { onRequest } = require('firebase-functions/v2/https'); exports.processPayment = onRequest( { secrets: ["SECRET_NAME"] }, (req, res) => { const myBillingService = initializeBillingService( // reference the secret value process.env.SECRET_NAME ); // Process the payment } );Python
import os from firebase_functions import https_fn @https_fn.on_request(secrets=["SECRET_NAME"]) def process_payment(req): myBillingService = initialize_billing(key=os.environ.get('SECRET_NAME')) # Process the payment ...部署 Cloud Functions:
firebase deploy --only functions
現在,您可以像存取其他環境變數一樣存取這個變數。相反地,如果另一個未指定密鑰的函式嘗試存取密鑰,則會收到未定義的值:
Node.js
exports.anotherEndpoint = onRequest((request, response) => { response.send(`The secret API key is ${process.env.SECRET_NAME}`); // responds with "The secret API key is undefined" because the `secrets` option is missing });Python
@https_fn.on_request() def another_endpoint(req): return https_fn.Response(f"The secret API key is {os.environ.get("SECRET_NAME")}") # Responds with "The secret API key is None" because the `secrets` parameter is missing.
函式部署完成後,就能存取 Secret 值。只有在 secrets 選項中明確包含 Secret 的函式,才能以環境變數的形式存取該 Secret。這有助於確保密鑰值只在需要時才可用,降低意外洩漏密鑰的風險。
管理密鑰
使用 Firebase CLI 管理密鑰。以這種方式管理密鑰時,請注意,部分 CLI 變更需要您修改和/或重新部署相關聯的函式。具體步驟包括:
- 每當您為密鑰設定新值時,都必須重新部署所有參照該密鑰的函式,才能採用最新值。
- 刪除 Secret 時,請確認沒有任何已部署的函式參照該 Secret。如果函式使用的 Secret 值已刪除,就會失敗,但不會顯示任何訊息。
以下是 Secret Manager 的 Firebase CLI 指令摘要:
# Change the value of an existing secret firebase functions:secrets:set SECRET_NAME # Set secret from file firebase functions:secrets:set SECRET_NAME --data-file file.json # Validate secret value as json cat file.json | firebase functions:secrets:set SECRET_NAME --format=json # Pipe from stdin and set secret cat file.json | firebase functions:secrets:set SECRET_NAME --format=json # 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 Manager 允許 6 個有效的密鑰版本,不需付費。也就是說,您每個月可以在 Firebase 專案中免費使用 6 個 Secret。
根據預設,Firebase CLI 會在適當情況下嘗試自動刪除未使用的 Secret 版本,例如使用新版 Secret 部署函式時。此外,您也可以使用 functions:secrets:destroy 和 functions:secrets:prune 主動清理未使用的 Secret。
Secret Manager 允許每月對密鑰執行 10,000 次免付費存取作業。每次冷啟動時,函式執行個體只會讀取 secrets 選項中指定的密鑰。如果有多個函式執行個體讀取大量 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 模擬器中的密鑰和憑證
Cloud Functions 模擬器支援使用密鑰儲存及存取機密設定資訊。根據預設,模擬器會嘗試使用應用程式預設憑證存取正式版密鑰。在某些情況下 (例如 CI 環境),模擬器可能會因權限限制而無法存取 Secret 值。
與 Cloud Functions 模擬器支援環境變數類似,您可以設定 .secret.local 檔案來覆寫 Secret 值。這樣一來,您就能輕鬆在本機測試函式,特別是在無法存取 Secret 值的情況下。
從執行階段設定遷移
functions.config API 已淘汰,將於 2027 年 3 月停用。
上述日期過後,使用 functions.config 的部署作業將會失敗。
為避免部署失敗,請使用 Firebase CLI 將設定遷移至 Cloud Secret Manager。強烈建議您採用這種做法,以最有效率且安全的方式遷移設定。
使用 Firebase CLI 匯出設定
使用
config export指令,將現有環境設定匯出至 Cloud Secret Manager 中的新密鑰:$ firebase functions:config:export i This command retrieves your Runtime Config values (accessed via functions.config()) and exports them as a Secret Manager secret. i Fetching your existing functions.config() from your project... ✔ Fetched your existing functions.config(). i Configuration to be exported: ⚠ This may contain sensitive data. Do not share this output. { ... } ✔ What would you like to name the new secret for your configuration? RUNTIME_CONFIG ✔ Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```更新函式程式碼以繫結 Secret
如要使用儲存在 Cloud Secret Manager 新密鑰中的設定,請在函式來源中使用
defineJsonSecretAPI。此外,請務必將 Secret 繫結至所有需要 Secret 的函式。之前
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });之後
const { onRequest } = require("firebase-functions/v2/https"); const { defineJsonSecret } = require("firebase-functions/params"); const config = defineJsonSecret("RUNTIME_CONFIG"); exports.myFunction = onRequest( // Bind secret to your function { secrets: [config] }, (req, res) => { // Access secret values via .value() const apiKey = config.value().someapi.key; // ... });部署函式
部署更新後的函式,套用變更並繫結 Secret 權限。
firebase deploy --only functions:<your-function-name>
自動填入的環境變數
系統會自動在函式執行階段和本機模擬函式中填入環境變數。包括由 Google Cloud 填入的變數,以及 Firebase 專屬環境變數:
process.env.FIREBASE_CONFIG:提供下列 Firebase 專案設定資訊:
{
databaseURL: 'https://DATABASE_NAME.firebaseio.com',
storageBucket: 'PROJECT_ID.firebasestorage.app ',
projectId: 'PROJECT_ID'
}
請注意,實際 Firebase 設定中的值可能會因您在專案中佈建的資源而異。
在不使用引數的情況下初始化 Firebase Admin SDK 時,系統會自動套用這項設定。如果您使用 JavaScript 編寫函式,請按照下列方式初始化:
const admin = require('firebase-admin');
admin.initializeApp();
如果您使用 TypeScript 編寫函式,請按照下列方式初始化:
import * as functions from 'firebase-functions/v1';
import * as admin from 'firebase-admin';
import 'firebase-functions/v1';
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);