設定環境


您通常需要為函式進行額外設定,例如第三方 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 中的密鑰。支援的類型如下:

  • 密鑰
  • 字串
  • 布林值
  • 整數
  • 浮點值

參數值和運算式

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 值區 (如果已在 Firebase 專案中啟用)。

這些函式在各方面都與使用者定義的字串參數類似,但由於 Firebase CLI 一律會知道這些函式的值,因此在部署時不會提示輸入值,也不會儲存至 .env 檔案。

密鑰參數

使用 defineSecret() 定義的 Secret 類型參數代表字串參數,這些參數的值儲存在 Cloud Secret Manager 中。密鑰參數會檢查 Cloud Secret Manager 中是否存在密鑰,並在部署期間互動式提示輸入新密鑰的值,而不是檢查本機 .env 檔案,並在缺少密鑰時將新值寫入檔案。

以這種方式定義的密鑰參數必須繫結至應有權存取這些參數的個別函式:

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 檔案、新增所需變數,然後部署:

  1. functions/ 目錄中建立 .env 檔案:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. 開啟 .env 檔案進行編輯,然後新增所需金鑰。例如:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. 部署函式並確認環境變數已載入:

    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 FirebaseGoogle Cloud Secret Manager 整合。這項加密服務會安全地儲存設定值,同時允許函式在需要時輕鬆存取。

建立及使用密鑰

如要建立密鑰,請使用 Firebase CLI。

如何建立及使用密鑰:

  1. 在本地專案目錄的根目錄中執行下列指令:

    firebase functions:secrets:set SECRET_NAME

  2. 輸入 SECRET_NAME 的值。

    CLI 會回覆成功訊息,並警告您必須部署函式,變更才會生效。

  3. 部署前,請確認函式程式碼允許函式使用 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
      });
  4. 部署 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

如為 accessdestroy 指令,您可以提供選用的版本參數來管理特定版本。例如:

functions:secrets:access SECRET_NAME[@VERSION]

如要進一步瞭解這些作業,請在指令中傳遞 -h,查看 CLI 說明。

Secret 的計費方式

Secret Manager 可免費提供 6 個有效密鑰版本。也就是說,每個 Firebase 專案每月可免費使用 6 個密鑰。

根據預設,Firebase CLI 會在適當情況下自動銷毀未使用的密鑰版本,例如部署含有新版密鑰的函式時。此外,您可以使用 functions:secrets:destroyfunctions:secrets:prune 主動清除未使用的密鑰。

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=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 進行環境設定,請務必在 2025 年底前,將現有設定遷移為環境變數 (採用 dotenv 格式),因為 functions.config 將於 2025 年底停用。Firebase CLI 提供匯出指令,可將目錄 .firebaserc 檔案中列出的每個別名或專案 (在下列範例中為 localdevprod) 的設定輸出為 .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,如「升級至第 2 代」一文所示。

環境設定

使用 CLI 設定環境設定

如要儲存環境資料,可以使用 Firebase CLI 中的 firebase functions:config:set 指令。您可以使用半形句號為每個鍵加上命名空間,將相關設定歸為一組。請注意,鍵只能使用小寫字元,不得使用大寫字元。

舉例來說,如要儲存「Some Service」的用戶端 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/v1');
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/v1');
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://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);