本頁面將引導您完成建置簡單的 Firebase 擴充功能所需的步驟,您可以將其安裝在專案中或與其他人共用。 Firebase 擴充功能的這個簡單範例將監視您的即時資料庫中的消息並將其轉換為大寫。
1. 設定環境並初始化項目
在開始建置擴充功能之前,您需要使用所需的工具設定建置環境。
安裝 Node.js 16 或更高版本。安裝 Node 的一種方法是使用nvm (或nvm-windows )。
安裝或更新至最新版本的Firebase CLI 。若要使用
npm
安裝或更新,請執行以下命令:npm install -g firebase-tools
現在使用 Firebase CLI 初始化一個新的擴充項目:
為您的擴充功能建立目錄並
cd
其中:mkdir rtdb-uppercase-messages && cd rtdb-uppercase-messages
執行 Firebase CLI 的
ext:dev:init
指令:firebase ext:dev:init
出現提示時,選擇 JavaScript 作為函數語言(但請注意,開發自己的擴充功能時也可以使用 TypeScript),並且當要求安裝依賴項時,回答「是」。 (接受任何其他選項的預設值。)此命令將為新擴充功能設定框架程式碼庫,您可以從中開始開發擴充功能。
使用firebase ext:dev:init
初始化新的擴充目錄。
2. 使用模擬器嘗試範例擴展
當 Firebase CLI 初始化新的擴充目錄時,它建立了一個簡單的範例函數和一個integration-tests
目錄,其中包含使用 Firebase 模擬器套件運行擴充功能所需的檔案。
嘗試在模擬器中運行範例擴充:
變更為
integration-tests
目錄:cd functions/integration-tests
使用示範專案啟動模擬器:
firebase emulators:start --project=demo-test
模擬器將擴充功能載入到預先定義的“虛擬”專案(
demo-test
)中。到目前為止,該擴充功能由一個 HTTP 觸發函數greetTheWorld
組成,該函數在訪問時傳回一條「hello world」訊息。在模擬器仍在運作的情況下,透過存取啟動擴充功能時列印的 URL 來嘗試擴充功能的
greetTheWorld
函數。您的瀏覽器會顯示訊息「來自問候世界的Hello World」。
此函數的原始碼位於擴充的
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); });
當模擬器運行時,它將自動重新載入您對 Functions 程式碼所做的任何變更。試著對
greetTheWorld
函數做一點小小的改變:函數/index.js
const greeting = `${consumerProvidedGreeting} everyone, from ${instanceId}`;
儲存您的變更。模擬器將重新載入您的程式碼,現在,當您造訪函數 URL 時,您將看到更新的問候語。
使用擴充模擬器可以讓您快速測試和迭代程式碼,從而加快開發速度。
更多資訊
了解有關使用擴展模擬器的更多資訊。
3.在extension.yaml中加入基本訊息
現在您已經設定了開發環境並正在運行擴展模擬器,您可以開始編寫自己的擴充功能。
作為適度的第一步,編輯預先定義的擴展元資料以反映您想要編寫的擴展,而不是greet-the-world
。此元資料儲存在extension.yaml
檔案中。
在編輯器中開啟
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 產品,後跟該擴充功能的描述。您應該在自己的擴充中使用相同的約定。由於您變更了擴充功能的名稱,因此也應該使用新名稱更新模擬器配置:
- 在
functions/integration-tests/firebase.json
中,將greet-the-world
改為rtdb-uppercase-messages
。 - 將
functions/integration-tests/extensions/greet-the-world.env
重新命名為functions/integration-tests/extensions/rtdb-uppercase-messages.env
。
- 在
您的擴充程式碼中仍然保留有一些greet-the-world
擴充的殘餘內容,但現在先保留它們。您將在接下來的幾節中更新這些內容。
extension.yaml
檔案包含有關您的擴充功能的元資料。最基本的元資料是您的擴充功能的名稱及其功能的描述。使用以下格式命名您的擴充功能:
<firebase-product>-<description-of-tasks-performed>
。
更多資訊
extension.yaml
參考具有該文件的完整規格;但是,本文檔將在您需要使用時討論該文件的具體用途。
4. 寫一個Cloud Function並宣告為擴充資源
現在您可以開始編寫一些程式碼了。在此步驟中,您將編寫一個雲端函數來執行擴展的核心任務,即監視即時資料庫中的消息並將其轉換為大寫。
在您選擇的編輯器或 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 模組語法(
import
和export
)而不是 CommonJS(require
)。若要在 Node 中使用 ES 模組,請在functions/package.json
中指定"type": "module"
:{ "name": "rtdb-uppercase-messages", "main": "index.js", "type": "module", … }
擴充功能中的每個函數都必須在
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"
由於您的擴充功能現在使用即時資料庫作為觸發器,因此您需要更新模擬器配置以與 Cloud Functions 模擬器一起執行 RTDB 模擬器:
如果模擬器仍在運行,請按 Ctrl-C 停止它。
從
functions/integration-tests
目錄中,執行下列指令:firebase init emulators
當詢問時,跳過設定預設項目,然後選擇“函數”和“資料庫”模擬器。接受預設連接埠並允許安裝工具下載任何所需的檔案。
重新啟動模擬器:
firebase emulators:start --project=demo-test
嘗試更新後的擴充功能:
使用啟動模擬器時列印的連結開啟資料庫模擬器 UI。
編輯資料庫的根節點:
- 欄位:
messages
- 類型:
json
- 值:
{"11": {"original": "recipe"}}
如果一切設定正確,當您儲存資料庫變更時,擴充功能的
makeuppercase
函數應觸發並為訊息 11 新增一則子記錄,其內容為"upper": "RECIPE"
。查看模擬器 UI 的日誌和資料庫標籤以確認預期結果。- 欄位:
嘗試在
messages
節點中新增更多子節點({"original":"any text"}
)。每當您新增記錄時,擴充功能都應新增一個uppercase
字段,其中包含original
字段的大寫內容。
您現在擁有一個在 RTDB 實例上運行的完整但簡單的擴充。在接下來的部分中,您將使用一些附加功能來完善此擴充功能。然後,您將準備好擴展以分發給其他人,最後,了解如何在擴展中心發布您的擴展。
- 構成擴充邏輯的函數必須定義為 Cloud Functions 程式碼,並在
extension.yaml
檔案中宣告為擴充資源。 - 您可以編寫在存取 HTTP 端點時觸發的函數,或是響應 Firebase 產品、Google Cloud 產品和其他擴充功能發出的事件而觸發的函數。
更多資訊
- 了解有關為擴展編寫 Cloud Functions 的更多信息,包括有關支援的事件觸發器的更多信息。
-
extension.yaml
參考具有該文件的完整規格;但是,本文檔將在您需要使用時討論該文件的具體用途。 - Cloud Functions for Firebase 文件包含有關使用 Cloud Functions 的一般信息,而不是特定於 Firebase Extensions 的資訊。
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 是必需的,本指南不需要。
- 在
extensions.yaml
的roles
欄位中聲明您的擴充功能所需的任何 IAM 角色。安裝後,擴充功能會自動被授予這些角色。 - 在
extensions.yaml
的apis
欄位中聲明您的擴充功能所需的任何 Google API。當使用者安裝您的擴充功能時,他們可以選擇自動為其專案啟用這些 API。 - 出於文件目的,請在
extensions.yaml
的externalServices
欄位中聲明您的擴充功能所需的任何非 Google API。
更多資訊
- 了解有關為擴展設定適當存取權限的更多資訊。
-
extension.yaml
參考具有該文件的完整規格;但是,本文檔將在您需要使用時討論該文件的具體用途。
6. 定義使用者可設定參數
您在最後兩個步驟中建立的函數監視傳入訊息的特定 RTDB 位置。有時,監視特定位置確實是您想要的,例如當您的擴充功能在您專門用於擴展的資料庫結構上運行時。但是,大多數時候,您希望讓在其專案中安裝您的擴充功能的使用者配置這些值。這樣,用戶就可以利用您的擴充功能來處理他們現有的資料庫設定。
使擴充功能監視新訊息的路徑可由使用者配置:
在
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
這定義了一個新的字串參數,用戶在安裝您的擴充功能時將被提示設定該參數。
仍然在
extension.yaml
檔案中,返回makeuppercase
聲明並將resource
欄位變更為以下內容:resource: projects/_/instances/${DATABASE_INSTANCE}/refs/${param:MESSAGE_PATH}
${param:MESSAGE_PATH}
標記是您剛剛定義的參數的參考。當您的擴充功能運行時,此令牌將被使用者為該參數配置的任何值替換,結果是makeuppercase
函數將偵聽使用者指定的路徑。您可以使用此語法在extension.yaml
中的任何位置引用任何使用者定義的參數(以及在POSTINSTALL.md
中 — 稍後會詳細介紹)。您也可以從函數程式碼存取使用者定義的參數。
在上一節中編寫的函數中,您對路徑進行了硬編碼以監視變更。更改觸發器定義以引用使用者定義的值:
函數/index.js
export const makeuppercase = database.ref(process.env.MESSAGE_PATH).onCreate
請注意,在 Firebase Extensions 中,此變更純粹是為了文件的目的:當將 Cloud Function 作為擴充的一部分部署時,它使用
extension.yaml
檔案中的觸發器定義並忽略函數定義中指定的值。儘管如此,最好在程式碼中記錄該值的來源。您可能會發現進行沒有運行時影響的程式碼變更會令人失望,但要吸取的重要教訓是您可以存取函數程式碼中的任何使用者定義參數並將其用作函數邏輯中的普通值。作為對此功能的認可,請新增以下日誌語句以證明您確實正在存取使用者定義的值:
函數/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. ...
通常,使用者在安裝擴充功能時會被提示提供參數值。但是,當您使用模擬器進行測試和開發時,您會跳過安裝過程,因此您可以使用
env
檔案為使用者定義的參數提供值。開啟
functions/integration-tests/extensions/rtdb-uppercase-messages.env
並將GREETING
定義替換為以下內容:MESSAGE_PATH=/msgs/{pushId}/original
請注意,上面的路徑與預設路徑和您之前定義的路徑不同;這只是為了在您嘗試更新的擴充功能時向自己證明您的定義正在生效。
現在,重新啟動模擬器並再次存取資料庫模擬器 UI。
使用上面定義的路徑編輯資料庫的根節點:
- 欄位:
msgs
- 類型:
json
- 值:
{"11": {"original": "recipe"}}
當您儲存資料庫變更時,擴充的
makeuppercase
函數應該像以前一樣觸發,但現在它還應該將使用者定義的參數列印到控制台日誌。- 欄位:
- 您可以透過在
extension.yaml
檔案中宣告使用者定義的參數,讓使用者能夠根據自己的需求自訂擴充功能。當使用者安裝您的擴充功能時,系統會提示您定義這些值。 - 您可以使用下列語法在
extension.yaml
檔案和POSTINSTALL.md
檔案中引用使用者定義的參數值:${param:PARAMETER_NAME}
- 您可以在 Cloud Functions 程式碼中以環境變數的形式存取使用者定義的參數值:
process.env.PARAMETER_NAME
- 使用模擬器進行測試時,請在
<extension-name>.env
檔案中定義使用者參數。
更多資訊
了解有關在擴充功能中設定和使用參數的更多資訊。
7.為使用者定義邏輯提供事件鉤子
身為擴充功能作者,您已經了解了 Firebase 產品如何觸發您的擴充功能提供的邏輯:在即時資料庫中建立新記錄會觸發您的makeuppercase
函數。您的擴充功能可以與安裝您的擴充功能的使用者俱有類似的關係:您的擴充功能可以觸發使用者定義的邏輯。
擴充可以提供同步鉤子、非同步鉤子或兩者。同步掛鉤為使用者提供了一種執行阻止擴充功能之一完成的任務的方法。這可能很有用,例如,可以為使用者提供一種在擴展完成工作之前執行自訂預處理的方法。
在本指南中,您將向您的擴充功能添加一個非同步掛鉤,這將使用戶能夠定義自己的處理步驟,以便在您的擴充功能將大寫訊息寫入即時資料庫後運行。非同步鉤子使用Eventarc來觸發使用者定義的函數。擴充功能聲明它們發出的事件類型,當使用者安裝擴充功能時,他們會選擇他們感興趣的事件類型。如果他們至少選擇一個事件,Firebase 將在安裝過程中為擴充功能提供一個 Eventarc 通道。然後,使用者可以部署自己的雲端函數,監聽該通道並在擴充功能發布新事件時觸發。
請依照以下步驟添加非同步掛鉤:
在
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
。)在
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
負載,其中包含原始訊息和大寫訊息。觸發事件的使用者定義函數可以利用此資訊。通常,
EVENTARC_CHANNEL
和EXT_SELECTED_EVENTS
環境變數是根據使用者在安裝過程中選擇的選項定義的。若要使用模擬器進行測試,請在rtdb-uppercase-messages.env
檔案中手動定義這些變數:EVENTARC_CHANNEL=locations/us-central1/channels/firebase EXT_SELECTED_EVENTS=test-publisher.rtdb-uppercase-messages.v1.complete
此時,您已完成將非同步事件掛鉤新增至擴充功能所需的步驟。
要嘗試您剛剛實現的這個新功能,在接下來的幾個步驟中,請假設正在安裝擴充功能的使用者的角色:
從
functions/integration-tests
目錄中,初始化一個新的Firebase專案:firebase init functions
出現提示時,拒絕設定預設項目,選擇 JavaScript 作為 Cloud Functions 語言,然後安裝所需的依賴項。該項目代表一個用戶的項目,其中安裝了您的擴充功能。
編輯
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
事件,並在觸發時向新大寫的訊息添加三個感嘆號。重新啟動模擬器。模擬器將載入擴充的函數以及「使用者」定義的後處理函數。
存取資料庫模擬器 UI 並使用上面定義的路徑編輯資料庫的根節點:
- 欄位:
msgs
- 類型:
json
- 值:
{"11": {"original": "recipe"}}
當您儲存資料庫變更時,擴充的
makeuppercase
函數和使用者的extraemphasis
函數應依序觸發,導致upper
欄位取得值RECIPE!!!
。- 欄位:
- 您的擴充功能可以包含掛鉤,讓使用者將自己的邏輯插入您的擴充功能的基本操作中。
- 使用者掛鉤可以是同步的,這會阻止擴充的執行,直到完成為止。擴充通常使用同步掛鉤來執行使用者定義的預處理任務。
- 用戶掛鉤也可以是異步的,如上面的範例所示。非同步掛鉤可用於運行使用者定義的邏輯,這對於擴充的正常運作並不重要。
更多資訊
了解有關為用戶定義邏輯添加掛鉤的更多信息,包括非同步和同步掛鉤。
8. 新增生命週期事件處理程序
到目前為止,您編寫的擴充功能會在訊息建立時對其進行處理。但是,如果您的用戶在安裝擴充功能時已經擁有訊息資料庫怎麼辦? Firebase Extensions 具有稱為生命週期事件掛鉤的功能,您可以使用該功能在安裝、更新或重新配置擴充功能時觸發操作。在本部分中,當使用者安裝您的擴充功能時,您將使用生命週期事件掛鉤以大寫訊息回填專案的現有訊息資料庫。
Firebase Extensions 使用 Cloud Tasks 來執行您的生命週期事件處理程序。您使用 Cloud Functions 定義事件處理程序;每當擴充功能的實例到達受支援的生命週期事件之一時,如果您定義了處理程序,它就會將該處理程序新增至 Cloud Tasks 佇列中。然後,Cloud Tasks 將非同步執行處理程序。當生命週期事件處理程序執行時,Firebase 控制台將向使用者報告擴充實例正在處理任務。由您的處理程序函數向使用者報告正在進行的狀態和任務完成。
若要新增回填現有訊息的生命週期事件處理程序,請執行下列操作:
定義一個由任務佇列事件觸發的新 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."); } });
請注意,該函數在將自身新增回任務佇列之前僅處理一些記錄。這是處理無法在雲端函數的逾時視窗內完成的處理任務的常用策略。由於您無法預測使用者安裝擴充功能時資料庫中可能已有多少訊息,因此此策略非常適合。
在
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
儘管回填現有訊息很好,但如果沒有它,擴充功能仍然可以運行。在這種情況下,您應該選擇執行生命週期事件處理程序。
為此,請為
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
事件處理程序,您需要在真實專案中安裝擴充功能。不過,這樣也好,因為新增了自動回填功能,教學擴充現在程式碼已完成!
當使用者執行某些擴展管理任務時會觸發生命週期事件:
- 安裝擴充實例
- 將擴充實例更新到新版本
- 重新配置擴充實例
您可以定義在擴展的生命週期事件上觸發的函數。
使用 Admin SDK 的擴充執行時間 API 將生命週期事件處理程序的狀態報告給使用者。使用者將在 Firebase 控制台中看到擴充功能的目前處理狀態。
在雲端函數逾時之前,對整個資料庫進行操作的函數(例如回填操作)通常無法完成。您可以將任務拆分為多個函數呼叫來避免此問題。
如果您的擴充功能包含對於擴充功能並不重要的生命週期事件處理程序,則您應該使處理程序的執行由使用者配置。
更多資訊
了解有關處理擴充功能生命週期事件的更多資訊。
9. 部署到真實的 Firebase 專案中
儘管擴充模擬器是在開發過程中快速迭代擴充的絕佳工具,但有時您會希望在實際專案中嘗試它。
為此,首先設定一個啟用一些服務的新項目:
- 在Firebase 控制台中,新增一個專案。
- 將您的專案升級到即用即付 Blaze 計劃。 Cloud Functions for Firebase 要求您的專案擁有結算帳戶,因此您還需要一個結算帳戶來安裝擴充功能。
- 在您的新專案中,啟用 Real-time Database 。
- 由於您想要測試擴充在安裝時回填現有資料的能力,因此請將一些範例資料匯入到即時資料庫實例中:
- 下載一些種子 RTDB 資料。
- 在 Firebase 控制台的即時資料庫頁面上,按一下 (更多)> 匯入 JSON ,然後選擇剛剛下載的檔案。
若要使回填功能能夠使用
orderByChild
方法,請將資料庫配置為根據upper
的值對訊息進行索引:{ "rules": { ".read": false, ".write": false, "messages": { ".indexOn": "upper" } } }
現在將本地來源的擴充功能安裝到新專案中:
為您的 Firebase 專案建立一個新目錄:
mkdir ~/extensions-live-test && cd ~/extensions-live-test
在工作目錄中初始化 Firebase 專案:
firebase init database
出現提示時,選擇您剛剛建立的項目。
將擴充功能安裝到本機 Firebase 專案中:
firebase ext:install /path/to/rtdb-uppercase-messages
您可以在此處了解使用 Firebase CLI 工具安裝擴充功能時的使用者體驗。當設定工具詢問您是否要回填現有資料庫時,請務必選擇「是」。
選擇配置選項後,Firebase CLI 會將您的配置儲存在
extensions
目錄中,並將擴充來源位置記錄在firebase.json
檔案中。這兩筆記錄統稱為擴充清單。使用者可以使用清單來保存其擴展配置並將其部署到不同的項目。將您的擴充配置部署到您的即時專案:
firebase deploy --only extensions
如果一切順利,Firebase CLI 應該將您的擴充功能上傳到您的專案並安裝它。安裝完成後,回填任務將運行,幾分鐘後,您的資料庫將使用大寫訊息進行更新。將一些新節點新增至訊息資料庫,並確保擴充功能也適用於新訊息。
- 使用者可以使用
firebase ext:install
指令建立擴充清單。您也可以使用此命令從本機來源安裝擴充功能。 - 使用
firebase deploy
將擴充配置從清單部署到即時專案。 - 儘管此處未演示,但用戶還可以從 Extensions Hub 將擴充功能安裝到其專案中。
更多資訊
請參閱有關使用擴充清單管理專案配置的使用者文件。
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
大多數擴充功能還提供自述文件,以便使用者存取擴充的儲存庫。您可以手動編寫此文件或使用命令產生自述文件。
出於本指南的目的,請跳過編寫自述文件。
附加文檔
上面討論的文檔是您應該向使用者提供的最小文檔集。許多擴充功能需要更詳細的文件才能讓使用者成功使用它們。在這種情況下,您應該編寫額外的文件並將其託管在您可以引導使用者存取的地方。
出於本指南的目的,請跳過編寫更廣泛的文件。
- 每個擴充功能至少應在以下文件中提供使用者文件:
extension.yaml
、PREINSTALL.md
、POSTINSTALL.md
和CHANGELOG.md
。 - 必要時您也應該向使用者提供更詳細的文件。
更多資訊
請參閱有關撰寫文件的文件。
11. 在擴展中心發布
現在您的擴充已完成代碼並記錄在案,您可以在擴展中心與全世界分享它。但由於這只是一個教程,因此不要實際這樣做。開始使用您在此處和 Firebase 擴展發布者文件的其餘部分中學到的知識來編寫您自己的擴展,並檢查由 Firebase 編寫的官方擴展的源代碼。
當您準備好在 Extensions Hub 上發布您的作品時,您可以按照以下步驟進行:
- 如果您要發布第一個擴展,請註冊為擴展發布者。當您註冊為擴充功能發佈者時,您將建立一個發布者 ID,讓使用者可以快速識別您作為擴充功能的作者。
將擴充功能的原始程式碼託管在可公開驗證的位置。當您的程式碼可從可驗證的來源取得時,Firebase 可以直接從此位置發布您的擴充功能。這樣做有助於確保您發布當前發布的擴充版本,並透過讓使用者檢查正在安裝到專案中的程式碼來幫助使用者。
目前,這意味著您的擴充功能可以在公共 GitHub 儲存庫中使用。
使用
firebase ext:dev:upload
指令將擴充功能上傳到擴充中心。前往 Firebase 控制台中的發布商資訊中心,找到您剛剛上傳的擴充程序,然後點擊「發佈到擴充中心」。這需要我們的審核人員進行審核,這可能需要幾天的時間。如果獲得批准,擴展將發佈到擴展中心。如果被拒絕,您將收到一條訊息解釋原因;然後,您可以解決報告的問題並重新提交以供審核。
- 要在擴展中心共享擴展,您必須註冊為發布者。
- 需要從可驗證的來源進行發布,這可以讓用戶確信他們正在安裝的程式碼與他們可以在 GitHub 上檢查的程式碼相同。
- 使用
firebase ext:dev:upload
指令將擴充功能上傳到擴充中心。 - 從發布商儀表板提交您的擴充功能以供審核。
更多資訊