開始建立擴充

本頁面將引導您完成建置簡單的 Firebase 擴充功能所需的步驟,您可以將其安裝在專案中或與其他人共用。 Firebase 擴充功能的這個簡單範例將監視您的即時資料庫中的消息並將其轉換為大寫。

1. 設定環境並初始化項目

在開始建置擴充功能之前,您需要使用所需的工具設定建置環境。

  1. 安裝 Node.js 16 或更高版本。安裝 Node 的一種方法是使用nvm (或nvm-windows )。

  2. 安裝或更新至最新版本的Firebase CLI 。若要使用npm安裝或更新,請執行以下命令:

    npm install -g firebase-tools
    

現在使用 Firebase CLI 初始化一個新的擴充項目:

  1. 為您的擴充功能建立目錄並cd其中:

    mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
    
  2. 執行 Firebase CLI 的ext:dev:init指令:

    firebase ext:dev:init
    

    出現提示時,選擇 JavaScript 作為函數語言(但請注意,開發自己的擴充功能時也可以使用 TypeScript),並且當要求安裝依賴項時,回答「是」。 (接受任何其他選項的預設值。)此命令將為新擴充功能設定框架程式碼庫,您可以從中開始開發擴充功能。

2. 使用模擬器嘗試範例擴展

當 Firebase CLI 初始化新的擴充目錄時,它建立了一個簡單的範例函數和一個integration-tests目錄,其中包含使用 Firebase 模擬器套件運行擴充功能所需的檔案。

嘗試在模擬器中運行範例擴充:

  1. 變更為integration-tests目錄:

    cd functions/integration-tests
    
  2. 使用示範專案啟動模擬器:

    firebase emulators:start --project=demo-test
    

    模擬器將擴充功能載入到預先定義的“虛擬”專案( demo-test )中。到目前為止,該擴充功能由一個 HTTP 觸發函數greetTheWorld組成,該函數在訪問時傳回一條「hello world」訊息。

  3. 在模擬器仍在運作的情況下,透過存取啟動擴充功能時列印的 URL 來嘗試擴充功能的greetTheWorld函數。

    您的瀏覽器會顯示訊息「來自問候世界的Hello World」。

  4. 此函數的原始碼位於擴充的functions目錄中。在您選擇的編輯器或 IDE 中開啟原始程式碼:

    函數/index.js

    const functions = require("firebase-functions");
    
    exports.greetTheWorld = functions.https.onRequest((req, res) => {
      // Here we reference a user-provided parameter
      // (its value is provided by the user during installation)
      const consumerProvidedGreeting = process.env.GREETING;
    
      // And here we reference an auto-populated parameter
      // (its value is provided by Firebase after installation)
      const instanceId = process.env.EXT_INSTANCE_ID;
    
      const greeting = `${consumerProvidedGreeting} World from ${instanceId}`;
    
      res.send(greeting);
    });
    
  5. 當模擬器運行時,它將自動重新載入您對 Functions 程式碼所做的任何變更。試著對greetTheWorld函數做一點小小的改變:

    函數/index.js

    const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
    

    儲存您的變更。模擬器將重新載入您的程式碼,現在,當您造訪函數 URL 時,您將看到更新的問候語。

3.在extension.yaml中加入基本訊息

現在您已經設定了開發環境並正在運行擴展模擬器,您可以開始編寫自己的擴充功能。

作為適度的第一步,編輯預先定義的擴展元資料以反映您想要編寫的擴展,而不是greet-the-world 。此元資料儲存在extension.yaml檔案中。

  1. 在編輯器中開啟extension.yaml ,並將檔案的全部內容替換為以下內容:

    name: rtdb-uppercase-messages
    version: 0.0.1
    specVersion: v1beta  # Firebase Extensions specification version; don't change
    
    # Friendly display name for your extension (~3-5 words)
    displayName: Convert messages to upper case
    
    # Brief description of the task your extension performs (~1 sentence)
    description: >-
      Converts messages in RTDB to upper case
    
    author:
      authorName: Your Name
      url: https://your-site.example.com
    
    license: Apache-2.0  # Required license
    
    # Public URL for the source code of your extension
    sourceUrl: https://github.com/your-name/your-repo
    

    請注意name欄位中使用的命名約定:官方 Firebase 擴充功能的命名帶有一個前綴,指示該擴充功能運行的主要 Firebase 產品,後跟該擴充功能的描述。您應該在自己的擴充中使用相同的約定。

  2. 由於您變更了擴充功能的名稱,因此也應該使用新名稱更新模擬器配置:

    1. functions/integration-tests/firebase.json中,將greet-the-world改為rtdb-uppercase-messages
    2. functions/integration-tests/extensions/greet-the-world.env重新命名為functions/integration-tests/extensions/rtdb-uppercase-messages.env

您的擴充程式碼中仍然保留有一些greet-the-world擴充的殘餘內容,但現在先保留它們。您將在接下來的幾節中更新這些內容。

4. 寫一個Cloud Function並宣告為擴充資源

現在您可以開始編寫一些程式碼了。在此步驟中,您將編寫一個雲端函數來執行擴展的核心任務,即監視即時資料庫中的消息並將其轉換為大寫。

  1. 在您選擇的編輯器或 IDE 中開啟擴充函數的原始程式碼(在擴充的functions目錄中)。將其內容替換為以下內容:

    函數/index.js

    import { database, logger } from "firebase-functions/v1";
    
    const app = initializeApp();
    
    // Listens for new messages added to /messages/{pushId}/original and creates an
    // uppercase version of the message to /messages/{pushId}/uppercase
    // for all databases in 'us-central1'
    export const makeuppercase = database
      .ref("/messages/{pushId}/uppercase")
      .onCreate(async (snapshot, context) => {
        // Grab the current value of what was written to the Realtime Database.
        const original = snapshot.val();
    
        // Convert it to upper case.
        logger.log("Uppercasing", context.params.pushId, original);
        const uppercase = original.toUpperCase();
    
        // Setting an "uppercase" sibling in the Realtime Database.
        const upperRef = snapshot.ref.parent.child("upper");
        await upperRef.set(uppercase);
    });
    

    您取代的舊函數是 HTTP 觸發的函數,它在存取 HTTP 端點時運行。新函數由即時資料庫事件觸發:它監視特定路徑上的新項目,當偵測到新項目時,它將值的大寫版本寫回資料庫。

    順便說一句,這個新檔案使用 ECMAScript 模組語法( importexport )而不是 CommonJS( require )。若要在 Node 中使用 ES 模組,請在functions/package.json中指定"type": "module"

    {
      "name": "rtdb-uppercase-messages",
      "main": "index.js",
      "type": "module",
      …
    }
    
  2. 擴充功能中的每個函數都必須在extension.yaml檔案中宣告。範例擴展聲明greetTheWorld作為擴展的唯一雲端函數;現在您已將其替換為makeuppercase ,您還需要更新其聲明。

    開啟extension.yaml並新增一個resources欄位:

    resources:
      - name: makeuppercase
        type: firebaseextensions.v1beta.function
        properties:
          eventTrigger:
            eventType: providers/google.firebase.database/eventTypes/ref.create
            # DATABASE_INSTANCE (project's default instance) is an auto-populated
            # parameter value. You can also specify an instance.
            resource: projects/_/instances/${DATABASE_INSTANCE}/refs/messages/{pushId}/original
          runtime: "nodejs18"
    
  3. 由於您的擴充功能現在使用即時資料庫作為觸發器,因此您需要更新模擬器配置以與 Cloud Functions 模擬器一起執行 RTDB 模擬器:

    1. 如果模擬器仍在運行,請按 Ctrl-C 停止它。

    2. functions/integration-tests目錄中,執行下列指令:

      firebase init emulators
      

      當詢問時,跳過設定預設項目,然後選擇“函數”和“資料庫”模擬器。接受預設連接埠並允許安裝工具下載任何所需的檔案。

    3. 重新啟動模擬器:

      firebase emulators:start --project=demo-test
      
  4. 嘗試更新後的擴充功能:

    1. 使用啟動模擬器時列印的連結開啟資料庫模擬器 UI。

    2. 編輯資料庫的根節點:

      • 欄位: messages
      • 類型: json
      • 值: {"11": {"original": "recipe"}}

      如果一切設定正確,當您儲存資料庫變更時,擴充功能的makeuppercase函數應觸發並為訊息 11 新增一則子記錄,其內容為"upper": "RECIPE" 。查看模擬器 UI 的日誌和資料庫標籤以確認預期結果。

    3. 嘗試在messages節點中新增更多子節點( {"original":"any text"} )。每當您新增記錄時,擴充功能都應新增一個uppercase字段,其中包含original字段的大寫內容。

您現在擁有一個在 RTDB 實例上運行的完整但簡單的擴充。在接下來的部分中,您將使用一些附加功能來完善此擴充功能。然後,您將準備好擴展以分發給其他人,最後,了解如何在擴展中心發布您的擴展。

5. 聲明API和角色

Firebase 使用每個實例的服務帳戶向已安裝擴充功能的每個實例授予對專案及其資料的有限存取權限。每個帳戶都具有操作所需的最低權限集。因此,您必須明確聲明您的擴充功能所需的任何 IAM 角色;當使用者安裝您的擴充功能時,Firebase 會建立一個授予這些角色的服務帳戶,並使用它來執行擴充功能。

您不需要聲明角色來觸發產品的事件,但您確實需要聲明角色才能與其互動。由於您在上一個步驟中新增的函數會寫入即時資料庫,因此您需要在extension.yaml中新增以下聲明:

roles:
  - role: firebasedatabase.admin
    reason: Allows the extension to write to RTDB.

同樣,您可以在apis欄位中聲明擴充功能使用的 Google API。當使用者安裝您的擴充功能時,系統會詢問他們是否要為其專案自動啟用這些 API。這通常僅對於非 Firebase Google API 是必需的,本指南不需要。

6. 定義使用者可設定參數

您在最後兩個步驟中建立的函數監視傳入訊息的特定 RTDB 位置。有時,監視特定位置確實是您想要的,例如當您的擴充功能在您專門用於擴展的資料庫結構上運行時。但是,大多數時候,您希望讓在其專案中安裝您的擴充功能的使用者配置這些值。這樣,用戶就可以利用您的擴充功能來處理他們現有的資料庫設定。

使擴充功能監視新訊息的路徑可由使用者配置:

  1. extension.yaml檔案中,新增params部分:

    - param: MESSAGE_PATH
      label: Message path
      description: >-
        What is the path at which the original text of a message can be found?
      type: string
      default: /messages/{pushId}/original
      required: true
      immutable: false
    

    這定義了一個新的字串參數,用戶在安裝您的擴充功能時將被提示設定該參數。

  2. 仍然在extension.yaml檔案中,返回makeuppercase聲明並將resource欄位變更為以下內容:

    resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
    

    ${param:MESSAGE_PATH}標記是您剛剛定義的參數的參考。當您的擴充功能運行時,此令牌將被使用者為該參數配置的任何值替換,結果是makeuppercase函數將偵聽使用者指定的路徑。您可以使用此語法在extension.yaml中的任何位置引用任何使用者定義的參數(以及在POSTINSTALL.md中 — 稍後會詳細介紹)。

  3. 您也可以從函數程式碼存取使用者定義的參數。

    在上一節中編寫的函數中,您對路徑進行了硬編碼以監視變更。更改觸發器定義以引用使用者定義的值:

    函數/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
    

    請注意,在 Firebase Extensions 中,此變更純粹是為了文件的目的:當將 Cloud Function 作為擴充的一部分部署時,它使用extension.yaml檔案中的觸發器定義並忽略函數定義中指定的值。儘管如此,最好在程式碼中記錄該值的來源。

  4. 您可能會發現進行沒有運行時影響的程式碼變更會令人失望,但要吸取的重要教訓是您可以存取函數程式碼中的任何使用者定義參數並將其用作函數邏輯中的普通值。作為對此功能的認可,請新增以下日誌語句以證明您確實正在存取使用者定義的值:

    函數/index.js

    export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate(
      async (snapshot, context) => {
        logger.log("Found new message at ", snapshot.ref);
    
        // Grab the current value of what was written to the Realtime Database.
        ...
    
  5. 通常,使用者在安裝擴充功能時會被提示提供參數值。但是,當您使用模擬器進行測試和開發時,您會跳過安裝過程,因此您可以使用env檔案為使用者定義的參數提供值。

    開啟functions/integration-tests/extensions/rtdb-uppercase-messages.env並將GREETING定義替換為以下內容:

    MESSAGE_PATH=/msgs/{pushId}/original
    

    請注意,上面的路徑與預設路徑和您之前定義的路徑不同;這只是為了在您嘗試更新的擴充功能時向自己證明您的定義正在生效。

  6. 現在,重新啟動模擬器並再次存取資料庫模擬器 UI。

    使用上面定義的路徑編輯資料庫的根節點:

    • 欄位: msgs
    • 類型: json
    • 值: {"11": {"original": "recipe"}}

    當您儲存資料庫變更時,擴充的makeuppercase函數應該像以前一樣觸發,但現在它還應該將使用者定義的參數列印到控制台日誌。

7.為使用者定義邏輯提供事件鉤子

身為擴充功能作者,您已經了解了 Firebase 產品如何觸發您的擴充功能提供的邏輯:在即時資料庫中建立新記錄會觸發您的makeuppercase函數。您的擴充功能可以與安裝您的擴充功能的使用者俱有類似的關係:您的擴充功能可以觸發使用者定義的邏輯。

擴充可以提供同步鉤子非同步鉤子或兩者。同步掛鉤為使用者提供了一種執行阻止擴充功能之一完成的任務的方法。這可能很有用,例如,可以為使用者提供一種在擴展完成工作之前執行自訂預處理的方法。

在本指南中,您將向您的擴充功能添加一個非同步掛鉤,這將使用戶能夠定義自己的處理步驟,以便在您的擴充功能將大寫訊息寫入即時資料庫後運行。非同步鉤子使用Eventarc來觸發使用者定義的函數。擴充功能聲明它們發出的事件類型,當使用者安裝擴充功能時,他們會選擇他們感興趣的事件類型。如果他們至少選擇一個事件,Firebase 將在安裝過程中為擴充功能提供一個 Eventarc 通道。然後,使用者可以部署自己的雲端函數,監聽該通道並在擴充功能發布新事件時觸發。

請依照以下步驟添加非同步掛鉤:

  1. extension.yaml檔案中,新增以下部分,該部分聲明擴充功能發出的一種事件類型:

    events:
      - type: test-publisher.rtdb-uppercase-messages.v1.complete
        description: >-
          Occurs when message uppercasing completes. The event subject will contain
          the RTDB URL of the uppercase message.
    

    事件類型必須是普遍唯一的;為了確保唯一性,請務必使用以下格式命名您的事件: <publisher-id>.<extension-id>.<version>.<description> 。 (您還沒有發布者 ID,所以現在只需使用test-publisher 。)

  2. makeuppercase函數的末尾,添加一些程式碼來發布您剛剛聲明的類型的事件:

    函數/index.js

    // Import the Eventarc library:
    import { initializeApp } from "firebase-admin/app";
    import { getEventarc } from "firebase-admin/eventarc";
    
    const app = initializeApp();
    
    // In makeuppercase, after upperRef.set(uppercase), add:
    
    // Set eventChannel to a newly-initialized channel, or `undefined` if events
    // aren't enabled.
    const eventChannel =
      process.env.EVENTARC_CHANNEL &&
      getEventarc().channel(process.env.EVENTARC_CHANNEL, {
        allowedEventTypes: process.env.EXT_SELECTED_EVENTS,
      });
    
    // If events are enabled, publish a `complete` event to the configured
    // channel.
    eventChannel &&
      eventChannel.publish({
        type: "test-publisher.rtdb-uppercase-messages.v1.complete",
        subject: upperRef.toString(),
        data: {
          "original": original,
          "uppercase": uppercase,
        },
      });
    

    此範例程式碼利用了以下事實:僅當使用者啟用至少一種事件類型時才定義EVENTARC_CHANNEL環境變數。如果未定義EVENTARC_CHANNEL ,則程式碼不會嘗試發布任何事件。

    您可以將額外資訊附加到 Eventarc 事件。在上面的範例中,事件具有一個subject字段,其中包含對新建立值的引用,以及一個data負載,其中包含原始訊息和大寫訊息。觸發事件的使用者定義函數可以利用此資訊。

  3. 通常, EVENTARC_CHANNELEXT_SELECTED_EVENTS環境變數是根據使用者在安裝過程中選擇的選項定義的。若要使用模擬器進行測試,請在rtdb-uppercase-messages.env檔案中手動定義這些變數:

    EVENTARC_CHANNEL=locations/us-central1/channels/firebase
    EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
    

此時,您已完成將非同步事件掛鉤新增至擴充功能所需的步驟。

要嘗試您剛剛實現的這個新功能,在接下來的幾個步驟中,請假設正在安裝擴充功能的使用者的角色:

  1. functions/integration-tests目錄中,初始化一個新的Firebase專案:

    firebase init functions
    

    出現提示時,拒絕設定預設項目,選擇 JavaScript 作為 Cloud Functions 語言,然後安裝所需的依賴項。該項目代表一個用戶的項目,其中安裝了您的擴充功能。

  2. 編輯integration-tests/functions/index.js並貼上以下程式碼:

    import { logger } from "firebase-functions/v1";
    import { onCustomEventPublished } from "firebase-functions/v2/eventarc";
    
    import { initializeApp } from "firebase-admin/app";
    import { getDatabase } from "firebase-admin/database";
    
    const app = initializeApp();
    
    export const extraemphasis = onCustomEventPublished(
      "test-publisher.rtdb-uppercase-messages.v1.complete",
      async (event) => {
        logger.info("Received makeuppercase completed event", event);
    
        const refUrl = event.subject;
        const ref = getDatabase().refFromURL(refUrl);
        const upper = (await ref.get()).val();
        return ref.set(`${upper}!!!`);
      }
    );
    

    這是使用者可能編寫的後處理函數的範例。在這種情況下,函數會偵聽擴充功能以發布complete事件,並在觸發時向新大寫的訊息添加三個感嘆號。

  3. 重新啟動模擬器。模擬器將載入擴充的函數以及「使用者」定義的後處理函數。

  4. 存取資料庫模擬器 UI 並使用上面定義的路徑編輯資料庫的根節點:

    • 欄位: msgs
    • 類型: json
    • 值: {"11": {"original": "recipe"}}

    當您儲存資料庫變更時,擴充的makeuppercase函數和使用者的extraemphasis函數應依序觸發,導致upper欄位取得值RECIPE!!!

8. 新增生命週期事件處理程序

到目前為止,您編寫的擴充功能會在訊息建立時對其進行處理。但是,如果您的用戶在安裝擴充功能時已經擁有訊息資料庫怎麼辦? Firebase Extensions 具有稱為生命週期事件掛鉤的功能,您可以使用該功能在安裝、更新或重新配置擴充功能時觸發操作。在本部分中,當使用者安裝您的擴充功能時,您將使用生命週期事件掛鉤以大寫訊息回填專案的現有訊息資料庫。

Firebase Extensions 使用 Cloud Tasks 來執行您的生命週期事件處理程序。您使用 Cloud Functions 定義事件處理程序;每當擴充功能的實例到達受支援的生命週期事件之一時,如果您定義了處理程序,它就會將該處理程序新增至 Cloud Tasks 佇列中。然後,Cloud Tasks 將非同步執行處理程序。當生命週期事件處理程序執行時,Firebase 控制台將向使用者報告擴充實例正在處理任務。由您的處理程序函數向使用者報告正在進行的狀態和任務完成。

若要新增回填現有訊息的生命週期事件處理程序,請執行下列操作:

  1. 定義一個由任務佇列事件觸發的新 Cloud Function:

    函數/index.js

    import { tasks } from "firebase-functions/v1";
    
    import { getDatabase } from "firebase-admin/database";
    import { getExtensions } from "firebase-admin/extensions";
    import { getFunctions } from "firebase-admin/functions";
    
    export const backfilldata = tasks.taskQueue().onDispatch(async () => {
      const batch = await getDatabase()
        .ref(process.env.MESSAGE_PATH)
        .parent.parent.orderByChild("upper")
        .limitToFirst(20)
        .get();
    
      const promises = [];
      for (const key in batch.val()) {
        const msg = batch.child(key);
        if (msg.hasChild("original") && !msg.hasChild("upper")) {
          const upper = msg.child("original").val().toUpperCase();
          promises.push(msg.child("upper").ref.set(upper));
        }
      }
      await Promise.all(promises);
    
      if (promises.length > 0) {
        const queue = getFunctions().taskQueue(
          "backfilldata",
          process.env.EXT_INSTANCE_ID
        );
        return queue.enqueue({});
      } else {
        return getExtensions()
          .runtime()
          .setProcessingState("PROCESSING_COMPLETE", "Backfill complete.");
      }
    });
    

    請注意,該函數在將自身新增回任務佇列之前僅處理一些記錄。這是處理無法在雲端函數的逾時視窗內完成的處理任務的常用策略。由於您無法預測使用者安裝擴充功能時資料庫中可能已有多少訊息,因此此策略非常適合。

  2. extension.yaml檔案中,將您的回填函數宣告為具有taskQueueTrigger屬性的擴充資源:

    resources:
      - name: makeuppercase
        ...
      - name: backfilldata
        type: firebaseextensions.v1beta.function
        description: >-
          Backfill existing messages with uppercase versions
        properties:
          runtime: "nodejs18"
          taskQueueTrigger: {}
    

    然後將該函數宣告為onInstall生命週期事件的處理程序:

    lifecycleEvents:
      onInstall:
        function: backfilldata
        processingMessage: Uppercasing existing messages
    
  3. 儘管回填現有訊息很好,但如果沒有它,擴充功能仍然可以運行。在這種情況下,您應該選擇執行生命週期事件處理程序。

    為此,請為extension.yaml新增一個參數:

    - param: DO_BACKFILL
      label: Backfill existing messages
      description: >-
        Generate uppercase versions of existing messages?
      type: select
      required: true
      options:
        - label: Yes
          value: true
        - label: No
          value: false
    

    然後在回填函數開始時,檢查DO_BACKFILL參數的值,如果未設定則提前退出:

    函數/index.js

    if (!process.env.DO_BACKFILL) {
      return getExtensions()
        .runtime()
        .setProcessingState("PROCESSING_COMPLETE", "Backfill skipped.");
    }
    

透過上述更改,該擴充功能現在在安裝時會將現有訊息轉換為大寫。

到目前為止,您已使用擴展模擬器來開發擴充功能並測試正在進行的變更。但是,擴充模擬器會跳過安裝過程,因此要測試onInstall事件處理程序,您需要在真實專案中安裝擴充功能。不過,這樣也好,因為新增了自動回填功能,教學擴充現在程式碼已完成!

9. 部署到真實的 Firebase 專案中

儘管擴充模擬器是在開發過程中快速迭代擴充的絕佳工具,但有時您會希望在實際專案中嘗試它。

為此,首先設定一個啟用一些服務的新項目:

  1. Firebase 控制台中,新增一個專案。
  2. 將您的專案升級到即用即付 Blaze 計劃。 Cloud Functions for Firebase 要求您的專案擁有結算帳戶,因此您還需要一個結算帳戶來安裝擴充功能。
  3. 在您的新專案中,啟用 Real-time Database
  4. 由於您想要測試擴充在安裝時回填現有資料的能力,因此請將一些範例資料匯入到即時資料庫實例中:
    1. 下載一些種子 RTDB 資料
    2. 在 Firebase 控制台的即時資料庫頁面上,按一下 (更多)> 匯入 JSON ,然後選擇剛剛下載的檔案。
  5. 若要使回填功能能夠使用orderByChild方法,請將資料庫配置為根據upper的值對訊息進行索引:

    {
      "rules": {
        ".read": false,
        ".write": false,
        "messages": {
          ".indexOn": "upper"
        }
      }
    }
    

現在將本地來源的擴充功能安裝到新專案中:

  1. 為您的 Firebase 專案建立一個新目錄:

    mkdir ~/extensions-live-test && cd ~/extensions-live-test
    
  2. 在工作目錄中初始化 Firebase 專案:

    firebase init database
    

    出現提示時,選擇您剛剛建立的項目。

  3. 將擴充功能安裝到本機 Firebase 專案中:

    firebase ext:install /path/to/rtdb-uppercase-messages
    

    您可以在此處了解使用 Firebase CLI 工具安裝擴充功能時的使用者體驗。當設定工具詢問您是否要回填現有資料庫時,請務必選擇「是」。

    選擇配置選項後,Firebase CLI 會將您的配置儲存在extensions目錄中,並將擴充來源位置記錄在firebase.json檔案中。這兩筆記錄統稱為擴充清單。使用者可以使用清單來保存其擴展配置並將其部署到不同的項目。

  4. 將您的擴充配置部署到您的即時專案:

    firebase deploy --only extensions
    

如果一切順利,Firebase CLI 應該將您的擴充功能上傳到您的專案並安裝它。安裝完成後,回填任務將運行,幾分鐘後,您的資料庫將使用大寫訊息進行更新。將一些新節點新增至訊息資料庫,並確保擴充功能也適用於新訊息。

10. 編寫文檔

在與用戶共享您的擴充功能之前,請確保您提供了足夠的文件以幫助他們取得成功。

當您初始化擴充專案時,Firebase CLI 建立了所需的最低文件的存根版本。更新這些文件以準確反映您所建置的擴充功能。

擴展.yaml

在開發此擴充功能時,您已經更新了此文件,因此您現在不需要進行任何更多更新。

但是,不要忽視此文件中包含的文件的重要性。除了擴展的關鍵識別資訊(名稱、描述、作者、官方儲存庫位置)之外, extension.yaml檔案還包含每個資源和使用者可設定參數的面向使用者的文件。此資訊會在 Firebase 控制台、擴充中心和 Firebase CLI 中向使用者顯示。

預先安裝.md

在此文件中,提供使用者在安裝擴充功能之前所需的資訊:簡要描述擴充功能的用途、解釋任何先決條件,並向使用者提供有關安裝擴充功能的計費影響的資訊。如果您有一個包含附加資訊的網站,這也是連結它的好地方。

該檔案的文字透過firebase ext:info指令在 Extensions Hub 中向使用者顯示。

以下是預安裝檔案的範例:

Use this extension to automatically convert strings to upper case when added to
a specified Realtime Database path.

This extension expects a database layout like the following example:

    "messages": {
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
      MESSAGE_ID: {
        "original": MESSAGE_TEXT
      },
    }

When you create new string records, this extension creates a new sibling record
with upper-cased text:

    MESSAGE_ID: {
      "original": MESSAGE_TEXT,
      "upper": UPPERCASE_MESSAGE_TEXT,
    }

#### Additional setup

Before installing this extension, make sure that you've
[set up Realtime Database](https://firebase.google.com/docs/database/quickstart)
in your Firebase project.

#### Billing

To install an extension, your project must be on the
[Blaze (pay as you go) plan](https://firebase.google.com/pricing).

- This extension uses other Firebase and Google Cloud Platform services, which
  have associated charges if you exceed the service's no-cost tier:
  - Realtime Database
  - Cloud Functions (Node.js 10+ runtime)
    [See FAQs](https://firebase.google.com/support/faq#extensions-pricing)
- If you enable events,
  [Eventarc fees apply](https://cloud.google.com/eventarc/pricing).

安裝後.md

此文件包含對用戶成功安裝您的擴充功能後有用的信息:例如,後續設定步驟、正在運行的擴充功能的範例等。

設定並安裝擴充功能後,POSINSTALL.md 的內容將顯示在 Firebase 控制台中。您可以在此文件中引用使用者參數,它們將被配置的值取代。

以下是教學擴充功能的安裝後檔案範例:

### See it in action

You can test out this extension right away!

1.  Go to your
    [Realtime Database dashboard](https://console.firebase.google.com/project/${param:PROJECT_ID}/database/${param:PROJECT_ID}/data) in the Firebase console.

1.  Add a message string to a path that matches the pattern `${param:MESSAGE_PATH}`.

1.  In a few seconds, you'll see a sibling node named `upper` that contains the
    message in upper case.

### Using the extension

We recommend adding data by pushing -- for example,
`firebase.database().ref().push()` -- because pushing assigns an automatically
generated ID to the node in the database. During retrieval, these nodes are
guaranteed to be ordered by the time they were added. Learn more about reading
and writing data for your platform (iOS, Android, or Web) in the
[Realtime Database documentation](https://firebase.google.com/docs/database/).

### Monitoring

As a best practice, you can
[monitor the activity](https://firebase.google.com/docs/extensions/manage-installed-extensions#monitor)
of your installed extension, including checks on its health, usage, and logs.

變更日誌.md

您還應該在CHANGELOG.md檔案中記錄您在擴充版本之間所做的變更。

由於範例擴充功能之前從未發布過,因此更改日誌只有一項:

## Version 0.0.1

Initial release of the _Convert messages to upper case_ extension.

自述文件.md

大多數擴充功能還提供自述文件,以便使用者存取擴充的儲存庫。您可以手動編寫此文件或使用命令產生自述文件。

出於本指南的目的,請跳過編寫自述文件。

附加文檔

上面討論的文檔是您應該向使用者提供的最小文檔集。許多擴充功能需要更詳細的文件才能讓使用者成功使用它們。在這種情況下,您應該編寫額外的文件並將其託管在您可以引導使用者存取的地方。

出於本指南的目的,請跳過編寫更廣泛的文件。

11. 在擴展中心發布

現在您的擴充已完成代碼並記錄在案,您可以在擴展中心與全世界分享它。但由於這只是一個教程,因此不要實際這樣做。開始使用您在此處和 Firebase 擴展發布者文件的其餘部分中學到的知識來編寫您自己的擴展,並檢查由 Firebase 編寫的官方擴展的源代碼。

當您準備好在 Extensions Hub 上發布您的作品時,您可以按照以下步驟進行:

  1. 如果您要發布第一個擴展,請註冊為擴展發布者。當您註冊為擴充功能發佈者時,您將建立一個發布者 ID,讓使用者可以快速識別您作為擴充功能的作者。
  2. 將擴充功能的原始程式碼託管在可公開驗證的位置。當您的程式碼可從可驗證的來源取得時,Firebase 可以直接從此位置發布您的擴充功能。這樣做有助於確保您發布當前發布的擴充版本,並透過讓使用者檢查正在安裝到專案中的程式碼來幫助使用者。

    目前,這意味著您的擴充功能可以在公共 GitHub 儲存庫中使用。

  3. 使用firebase ext:dev:upload指令將擴充功能上傳到擴充中心。

  4. 前往 Firebase 控制台中的發布商資訊中心,找到您剛剛上傳的擴充程序,然後點擊「發佈到擴充中心」。這需要我們的審核人員進行審核,這可能需要幾天的時間。如果獲得批准,擴展將發佈到擴展中心。如果被拒絕,您將收到一條訊息解釋原因;然後,您可以解決報告的問題並重新提交以供審核。