您通常需要函式的額外設定,例如第三方 API 金鑰或可調整的設定。Cloud Functions 專用的 Firebase SDK 提供內建的環境設定,方便您為專案儲存及擷取這類類型的資料。
選項有以下三種:
- 參數化設定 (適用於多數情況)。這可提供強型環境設定,其中包含在部署時驗證的參數,以防止錯誤並簡化偵錯作業。
- 環境變數的檔案型設定。如果使用這個方法,您將手動建立用於載入環境變數的 dotenv 檔案。
- 使用 Firebase CLI 和
functions.config
(僅限 Cloud Functions (第 1 代)) 的執行階段環境設定。
在大多數情況下,建議您採用參數化設定。此方法可在執行階段和部署期間提供設定值,並禁止部署,除非所有參數都具備有效值。相反地,在部署期間無法使用環境變數的設定。
參數化設定
Cloud Functions for Firebase 提供介面,可讓您在程式碼集中透過宣告定義設定參數。這些參數的值可在函式部署期間、設定部署和執行階段選項,以及在執行期間使用。這表示除非所有參數具備有效的值,否則 CLI 會封鎖部署作業。
如要在程式碼中定義參數,請按照以下模型操作:
const functions = require('firebase-functions');
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 中的密鑰。支援的類型如下:
- 密鑰
- 字串
- 布林值
- 整數
- 浮點值
參數值和運算式
Firebase 會在部署時間和函式執行期間評估參數。由於這種雙重環境,您在比較參數值,以及使用這些參數設定函式的執行階段選項時,必須格外小心。
如要將參數做為執行階段選項傳遞至函式,請直接傳送參數:
const functions = require('firebase-functions');
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');
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');
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 值區 (如果在 Firebase 專案中啟用)。
這些函式就像使用者定義的字串參數,在任何方面都一樣,但由於其值一律會顯示在 Firebase CLI 中,因此值不會在部署時提示輸入,也不會儲存至 .env
檔案。
密鑰參數
使用 defineSecret()
定義的 Secret
類型參數代表含有儲存在 Cloud Secret Manager 值的字串參數。請在 Cloud Secret Manager 中檢查密鑰參數是否存在,並在部署期間透過互動方式提示新密鑰的值,而不要檢查本機的 .env
檔案並在缺少時寫入新的值。
以這種方式定義的密鑰參數必須繫結至個別應有存取權的函式:
const functions = require('firebase-functions');
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=人類 |
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 專案
- GCLOUD_PROJECT
- GOOGLE_CLOUD_PROJECT
- FUNCTION_TRIGGER_TYPE
- FUNCTION_NAME
- FUNCTION_MEMORY_MB
- FUNCTION_TIMEOUT_SEC
- FUNCTION_IDENTITY
- 區域
- FUNCTION_TARGET
- FUNCTION_SIGNATURE_TYPE
- K_SERVICE
- K_REVISION
- 通訊埠
- K_設定
儲存及存取機密設定資訊
儲存在 .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
});
部署函式之後,這個函式即可存取密鑰值。「只有」在 runWith
參數中明確包含密鑰的函式,才能以環境變數的形式存取該密鑰。這有助於確保密鑰值只在必要時使用,降低不小心外洩密鑰的風險。
管理密鑰
請使用 Firebase CLI 管理密鑰。請注意,透過這種方式管理密鑰時,請注意部分 CLI 變更需要您修改和/或重新部署相關聯的函式。具體步驟包括:
- 每次設定密鑰的新值時,您必須重新部署參照該密鑰的所有函式,使其擁有最新的值。
- 如果您刪除密鑰,請確認所有部署的函式都未參照該密鑰。如果函式使用已刪除密鑰值,則會失敗,而且不會顯示相關通知。
以下摘要說明適用於密鑰管理的 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 Manager 允許 6 個有效的密鑰版本,無須額外付費。這表示在 Firebase 專案中,每月可免費使用 6 個密鑰。
根據預設,Firebase CLI 在適當情況下會嘗試自動刪除未使用的密鑰版本,例如使用新版密鑰部署函式時。此外,您可以使用 functions:secrets:destroy
和 functions:secrets:prune
主動清除未使用的密鑰。
Secret Manager 允許對 Secret Manager 每月 10,000 個未計費的存取作業。每當函式執行個體冷啟動時,就只會讀取 runWith
參數中指定的密鑰。如果您有許多函式執行個體讀取大量密鑰,專案可能會超出這個上限,屆時每 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=人類 |
AUDIENCE=Dev Humans | AUDIENCE=當地人 |
在本機環境中啟動時,模擬器會載入環境變數,如下所示:
$ 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
使用環境設定,則可以以環境變數 (dotenv 格式) 的形式遷移現有設定。Firebase CLI 提供匯出指令,會以 .env
檔案的形式,輸出目錄 .firebaserc
檔案 (如下方範例、local
、dev
和 prod
) 中所列的每個別名或專案。
如要遷移,請使用 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
,如升級至第 2 代所示。
環境設定
在 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}
});
});
使用環境設定初始化模組
部分節點模組已準備就緒,不需進行任何設定。其他模組則需要額外的設定,才能正確初始化。建議您將這項設定儲存在環境變數中,而不要以硬式編碼方式寫入。這樣可以讓程式碼保持可攜性,進而開發應用程式的原始碼,或輕鬆在實際工作環境和測試版本之間切換。
舉例來說,如要使用 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);