您通常需要為函式進行額外設定,例如第三方 API 金鑰或可調整的設定。Firebase SDK for Cloud Functions 提供內建的環境設定,方便您儲存及擷取專案的這類資料。
可選擇的選項如下:
- 參數化設定 (建議用於大多數情境)。這會提供強型別環境設定,並在部署時驗證參數,避免發生錯誤及簡化偵錯程序。
- 以檔案為基礎設定環境變數。使用這種方法時,您需要手動建立 dotenv 檔案,載入環境變數。
在多數情況下,建議使用參數化設定。這種做法可讓設定值在執行階段和部署階段都可用,且除非所有參數都有有效值,否則部署作業會遭到封鎖。反之,部署時無法使用環境變數設定。
參數化設定
Cloud Functions for Firebase 提供介面,可在程式碼集內以宣告方式定義設定參數。您可以在函式部署期間、設定部署和執行階段選項時,以及執行期間,取得這些參數的值。也就是說,除非所有參數都有有效值,否則 CLI 會封鎖部署作業。
如要在程式碼中定義參數,請按照下列範本操作:
const functions = require('firebase-functions/v1');
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 = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
res.send(`${welcomeMessage.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()。這個回呼會在任何函式於正式環境中執行前執行,但不會在部署期間呼叫,因此是存取參數值的安全位置。
const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v1');
const apiKey = defineSecret('GOOGLE_API_KEY');
let genAI;
onInit(() => {
genAI = new GoogleGenerativeAI(apiKey.value());
})
設定 CLI 行為
您可以透過 Options 物件設定參數,控管 CLI 提示輸入值的方式。下列範例會設定選項,驗證電話號碼格式、提供簡單的選取選項,以及從 Firebase 專案自動填入選取選項:
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: {select: {options:
[{value: "odd"}, {value: "even"}]}}})
const storageBucket = defineString('BUCKET', {input: {resource: {type:
"storage.googleapis.com/Bucket"}}, description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets"})
參數類型
參數化設定可為參數值提供嚴格型別,並支援 Cloud Secret Manager 中的密鑰。支援的類型包括:
- 密鑰
- 字串
- 布林值
- 整數
- 浮點值
如要瞭解定義參數的函式,請參閱 params 命名空間參考資料。
參數值和運算式
Firebase 會在部署時和函式執行期間評估參數。由於有這兩個環境,比較參數值時必須格外小心,使用參數值為函式設定執行階段選項時也是如此。
如要以執行階段選項的形式將參數傳遞至函式,請直接傳遞:
const functions = require('firebase-functions/v1');
const { defineInt} = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
//…
此外,如要比較參數以瞭解該選擇哪個選項,您需要使用內建比較子,而不是檢查值:
const functions = require('firebase-functions/v1');
const { defineBool } = require('firebase-functions/params');
const environment = params.defineString(‘ENVIRONMENT’, {default: ‘dev’});
// use built-in comparators
const minInstancesConfig =environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
//…
如要存取僅在執行階段使用的參數和參數運算式,可以使用 value 函式:
const functions = require('firebase-functions/v1');
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 = functions.https.onRequest(
(req, res) => {
res.send(`${welcomeMessage.value()}! I am a function.`);
}
);
內建參數
Cloud Functions SDK 提供三個預先定義的參數,可從 firebase-functions/params 子套件取得:
projectID:函式執行的 Cloud 專案。databaseURL:與函式相關聯的即時資料庫執行個體網址 (如果已在 Firebase 專案中啟用)。storageBucket:與函式相關聯的 Cloud Storage bucket (如果已在 Firebase 專案中啟用)。
這些函式在各方面都與使用者定義的字串參數類似,但由於 Firebase CLI 一律會知道這些函式的值,因此系統不會在部署時提示輸入值,也不會將值儲存至 .env 檔案。
密鑰參數
使用 defineSecret() 定義的 Secret 類型參數代表字串參數,這些參數的值儲存在 Cloud Secret Manager 中。密鑰參數會檢查 Cloud Secret Manager 中是否存在密鑰,並在部署期間互動式提示輸入新密鑰的值,而不是檢查本機 .env 檔案,並在缺少密鑰時將新值寫入檔案。
以這種方式定義的 Secret 參數必須繫結至應有權存取這些參數的個別函式:
const functions = require('firebase-functions/v1');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');
export const postToDiscord = functions.runWith({ secrets: [discordApiKey] }).https.onRequest(
(req, res) => {
const apiKey = discordApiKey.value();
//…
環境變數
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 整合。 這項加密服務可安全地儲存設定值,同時允許函式在需要時輕鬆存取。
建立及使用密鑰
如要建立密鑰,請使用 Firebase CLI。
如何建立及使用密鑰:
在本地專案目錄的根目錄中執行下列指令:
firebase functions:secrets:set SECRET_NAME
輸入 SECRET_NAME 的值。
CLI 會回傳成功訊息,並警告您必須部署函式,變更才會生效。
部署前,請確認函式程式碼允許函式使用
runWith參數存取密鑰: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 中指定密鑰的函式嘗試存取密鑰,則會收到未定義的值:
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。這有助於確保只有在需要時才能存取密鑰值,降低密鑰意外外洩的風險。
管理密鑰
使用 Firebase CLI 管理密鑰。以這種方式管理密鑰時,請注意,部分 CLI 變更需要您修改及/或重新部署相關聯的函式。具體步驟包括:
- 每當您為密鑰設定新值時,都必須重新部署參照該密鑰的所有函式,才能取得最新值。
- 刪除 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 個有效密鑰版本。也就是說,每個 Firebase 專案每月可免費使用 6 個密鑰。
根據預設,Firebase CLI 會在適當情況下自動銷毀未使用的密鑰版本,例如部署含有新版密鑰的函式時。此外,您也可以使用 functions:secrets:destroy 和 functions:secrets:prune 主動清除未使用的密鑰。
Secret Manager 允許每月對密鑰執行 10,000 次免付費存取作業。函式執行個體每次冷啟動時,只會讀取 secrets 選項中指定的密鑰。如果大量函式例項讀取大量密鑰,專案可能會超過這項配額,屆時系統會針對每 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 環境等特定情況下,模擬器可能因權限限制而無法存取密鑰值。
與 Cloud Functions 模擬器支援環境變數類似,您可以設定 .secret.local 檔案,覆寫密鑰值。這樣您就能輕鬆在本機測試函式,特別是在無法存取密鑰值的情況下。
從執行階段設定遷移
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```更新函式程式碼以繫結密鑰
如要在 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; // ... });部署函式
部署更新後的函式,套用變更並繫結密鑰權限。
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);