במדריך הזה מוסבר איך להעביר את התוספים שלכם מהסביבה Firebase Extensions שיצאה משימוש לפונקציה שהמשתמשים שלכם מתקינים ומפעילים ב-Cloud Functions שלהם עבור Firebase (דור שני) בסיס קוד.
זו הדרך המומלצת להעברה. Firebase ינהל רשימה של תוספים עם מקבילות רשמיות ב-npm. במדריך הזה מוסבר איך ליצור תוסף משלכם.
במדריך הזה, נעשה שימוש בתוסף Stream Firestore to BigQuery (firestore-bigquery-export) כדוגמה. בסוף כל קטע יש דוגמה עם הסבר שמראה איך התוסף נראה לפני ההעברה ואיך הוא נראה אחרי ההעברה, בתור חבילת @firebase/firestore-bigquery-export.
הרשמה לקבלת מידע נוסף ועזרה בהעברת תוספים
אם יש לך שאלות לגבי המעבר מ-Firebase Extensions, אפשר לפנות אלינו בכתובת firebase-extensions-migrator-support-external@google.com. נשלח אימייל לקבוצה הזו גם כשנעדכן את המדריך עם מידע נוסף על אריזה, בדיקה והפצה של פונקציות מהדור השני.
כדי להצטרף לקבוצה הזו, צריך לשלוח הודעה לכתובת firebase-extensions-migrator-support-external+subscribe@google.com, ולקבל בתגובה אימייל עם בקשה להצטרפות. צריך להשיב לאימייל הזה ולא ללחוץ על הלחצן 'הצטרפות לקבוצה הזו'.
לפני שמתחילים
כדי להשלים את ההעברה הזו, תשתמשו בתכונות הבאות של Cloud Functions:
הגדרה עם פרמטרים. כל פרמטר שמצהירים עליו ב-
extension.yamlהופך לפרמטר מוגדר בקוד החבילה.תפקידי IAM דקלרטיביים וממשקי API נדרשים כל תפקיד שמצהירים עליו ב-
extension.yamlהופך לקריאה ל-requiresRole(...), וכל API הופך לקריאה ל-requiresAPI(...)בקוד הפונקציה. בזמן הפריסה, Firebase CLI מקצה את התפקידים שהוגדרו לחשבון של שירות זמן ריצה מנוהל, ומפעיל את ממשקי ה-API שהוגדרו בשמכם.אירועים במחזור החיים של בסיסי קוד Cloud Functions. בבסיסי קוד Cloud Functions יש עכשיו תמיכה באירועים של מחזור חיים בדומה ל-Firebase Extensions. הצהרה על הגדרות בזמן ההתקנה ובזמן העדכון באמצעות ה-lifecycle hooks
afterFirstDeploy(...)ו-afterRedeploy(...). הם מחליפים את התגlifecycleEventsשמוצהר ב-extension.yaml.
מלאי התוסף
מתחילים במלאי של התוסף: רשימה מלאה של כל מה שהתוסף מצהיר, שולח ומתעד, כך שלכל התנהגות תהיה יעד מוגדר בפונקציה מהדור השני, ושום דבר לא יאבד במהלך ההעברה.
צריך לבדוק את כל אחד מהדברים הבאים ולרשום את מה שמוצאים:
extension.yaml, שבו מצהירים על הפרמטרים, הפונקציות, האירועים, תפקידי ה-IAM, ממשקי ה-API הנדרשים, הסודות וה-lifecycle hooks.
functions/, שמכיל את קוד הפונקציה, יחסי התלות, הגדרות הבנייה, הטריגרים והפונקציות של תור המשימות.README.md,PREINSTALL.mdו-POSTINSTALL.md, שכוללים שלבי הגדרה, אזהרות והערות בנושא חיוב.
scripts/, שמכיל כלי ייבוא, מילוי חוסרים, IAM, תיקון או העברה, וכל כלי אחר שאתם שולחים יחד עם התוסף.
לאחר מכן, לכל פריט ב-extension.yaml, מחליטים איפה הוא יופיע בחבילת npm:
המרת הגדרות משתמשים לפרמטרים של Cloud Functions (קטע 5).
המרת סודות לCloud Functions סודות (קטע 6).
המרת תפקידי IAM להצהרות
requiresRole(...)(סעיף 8).המרת ממשקי Google API נדרשים להצהרות
requiresAPI(...)במקומות המתאימים (סעיף 8).המרת ווים של התקנה ועדכון להצהרות
afterFirstDeploy(...)ו-afterRedeploy(...)(סעיף 8).
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
קריאה של firestore-bigquery-export/extension.yaml ושל functions/ יוצרת את המלאי הבא:
| ב-extension.yaml | ספירה / ערך | לאן המידע מועבר |
|---|---|---|
| params | 25 (COLLECTION_PATH, DATASET_ID, TABLE_ID, DATASET_LOCATION, VIEW_TYPE, …) | Cloud Functions פרמטרים (סעיף 5) |
| apis | bigquery.googleapis.com | requiresAPI(...) (סעיף 7) |
| roles | bigquery.dataEditor, datastore.user, bigquery.user | requiresRole(...) (section 7) |
| משאבים | טריגר אחד לאירוע (fsexportbigquery) + פונקציות של תור משימות (initBigQuerySync, setupBigQuerySync) | פונקציות של חבילה שיוצאו (סעיף 3) |
| lifecycleEvents | onInstall → initBigQuerySync; onUpdate / onConfigure → setupBigQuerySync | afterFirstDeploy / afterRedeploy (סעיף 9) |
| scripts/ | import/ (backfill), gen-schema-view/ | נשמרים כסקריפטים (לא רלוונטיים כאן) |
התוסף לא מגדיר סוג: פרמטרים סודיים, ולכן אין מה להעביר בסעיף 6 במדריך הזה. הטריגר לאירוע כבר שייך לדור השני. רק הפונקציות של תור המשימות עדיין שייכות לדור הראשון (רלוונטי בקטע 3).
עדכון הקובץ package.json
מעדכנים את קובץ package.json של התוסף. אם מעבירים תוסף אחד, אפשר להשתמש בתיקיית הבסיס package.json. אם מעבירים הרבה תוספים במאגר אחד, צריך לתת לכל תוסף חבילה משלו.
גרסאות SDK מינימליות. מגדירים את firebase-functions >= 7.3 ואת firebase-admin >= 14.2.0 כתלות. צריך להצהיר על הגרסה של firebase-functions כעל peer dependency
{
"name": "<package-name>",
"version": "1.0.0",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": {
"types": "./lib/index.d.ts",
"default": "./lib/index.js"
}
},
"engines": {
"node": ">=22"
},
"peerDependencies": {
"firebase-functions": "^7.3.0"
},
"dependencies": {
"firebase-functions": "^7.3.0",
"firebase-admin": "^14.2.0"
}
}
צריך להצהיר על firebase-functions כתלות ברמת העמיתים בנוסף לתלות הרגילה, כדי שלפרויקט Cloud Functions של המשתמשים תהיה אותה גרסה של ה-SDK שבה נכתבה הספרייה.
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
לפני. הקובץ functions/package.json של התוסף הוא פרטי, מצוין בו מזהה התוסף ומוצהר בו ש-firebase-functions הוא תלות ישירה:
{
"name": "firestore-bigquery-export",
"main": "lib/index.js",
"private": true,
"dependencies": {
"@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
"firebase-admin": "^14.2.0",
"firebase-functions": "^6.3.2"
}
}
אחרי. חבילה שאפשר לפרסם: שם עם היקף, מפת ייצוא ו-firebase-functions הועבר אל peerDependencies:
{
"name": "@firebase/firestore-bigquery-export",
"version": "0.1.0",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": { "types": "./lib/index.d.ts", "default": "./lib/index.js" }, },
"engines": { "node": ">=22" },
"peerDependencies": { "firebase-functions": "^7.3.0" },
"dependencies": {
"@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4",
"firebase-admin": "^14.2.0",
"firebase-functions": "^7.3.0"
}
}
שדרוג פונקציות מדור ראשון לדור שני
אם התוסף עדיין מייצא פונקציות מהדור הראשון, צריך להמיר כל פונקציה למקבילה שלה מהדור השני. מייבאים ממודולי firebase-functions/... ומעבירים הגדרות של זמן ריצה באפשרויות הפונקציה.
אתם יכולים לצמצם את המאמצים הנדרשים לכתיבה מחדש באמצעות פירוק מובנה של אירועים בגרסה השנייה של ה-SDK, ולהימנע מכתיבה מחדש של הלוגיקה של הפונקציה, כי גרסה 2 של ה-SDK חושפת עכשיו את הפרמטרים של גרסה 1 כשדות באובייקט האירוע. כך תוכלו להשתמש בפרמטרים מפורקים או בעלי שם, ולשמור על הלוגיקה העסקית שלכם ללא שינוי.
לפני. דור ראשון:
import * as functions from "firebase-functions/v1";
export const sync = functions.firestore
.document("{collectionId}/{documentId}")
.onWrite(async (change, context) => {
await handleWrite(change.before, change.after, context.params);
});
אחרי. דור שני:
import { onDocumentWritten } from "firebase-functions/firestore";
export const syncV2 = onDocumentWritten(
{ document: "{collectionId}/{documentId}" },
async ({change,context}) =>
await handleWrite(change.before, change.after, context.params);
);
ראו את Cloud Functions השוואת גרסאות לקבלת רשימה מקיפה של הבדלים בין פונקציות דור ראשון לדור שני.
המרת פרמטרים וסודות של תוספים
פרמטרים של המרה
כל פרמטר שמצהירים עליו ב-extension.yaml הופך לפרמטר Cloud Functions.
המרת קריאות ישירות של הסביבה:
const collectionPath = process.env.COLLECTION_PATH;
לתוך הפרמטרים Cloud Functions:
import { defineString } from "firebase-functions/params";
import { onDocumentWritten} from "firebase-functions/firestore";
const collectionPath = defineString("COLLECTION_PATH");
// Pass the param directly when used as a placeholder (e.g. trigger path)
export const sync = onDocumentWritten(
{ document: collectionPath },
async (event) => {
// Call .value() to read the string inside a handler
const path = collectionPath.value();
await handleWrite(path, event);
}
);
משתמשים ב-collectionPath.value() כדי לקרוא את המחרוזת בתוך handler, וב-collectionPath ישירות במקום שבו צפוי פלייסהולדר, כמו נתיב להפעלת פונקציה.
ממשק Firebase CLI מאתר את הפרמטרים וקורא את הערכים שלהם מ- .env, .env.projectId או מציג למשתמשים הנחיות במהלך הפריסה. חשוב להשתמש באותם שמות פרמטרים כדי שהערכים מההתקנה הקיימת יועברו.
חשוב לא לשנות את שמות הפרמטרים שהוגדרו בקוד בשום אופן. העברת התוסף תשמור באופן אוטומטי את ערך הפרמטר הקיים של משתמש הקצה, אבל רק אם השמות לא ישתנו.
דוגמה: העברת נתונים מ-Firestore ל-BigQuery
לפני. פרמטר שהוגדר ב-extension.yaml, נקרא כמשתנה סביבה גולמי ב-config.ts:
# extension.yaml
- param: COLLECTION_PATH
label: Collection path
type: string
required: true
// functions/src/config.ts
collectionPath: process.env.COLLECTION_PATH,
אחרי. defineString אחד; ה-CLI מאתר אותו וקורא מ-.env:
// src/config.ts
import { defineString } from "firebase-functions/params";
collectionPath: defineString("COLLECTION_PATH", {
label: "Collection path",
// We now support "nonEmpty: true" to ensure a value other than the empty string
// is entered, analagous to "required: true" in extensions.yaml
input: { text: { nonEmpty: true} }
}),
שם הפרמטר לא משתנה, כך שקובץ .env קיים ימשיך לפעול.
המרת סודות
ב-extension.yaml, מגדירים סודות באמצעות type: secret. סביבת זמן הריצה של התוספים מאחסנת אותם ומקשרת אותם, כך שקוד התוסף יכול לקרוא את process.env.PARAM_NAME ישירות. בבסיס קוד טיפוסי של Cloud Functions, אתם מצהירים על כל סוד ומקשרים אותו באופן מפורש:
import { defineSecret } from "firebase-functions/params";
import { onRequest } from "firebase-functions/https";
const apiKey = defineSecret("API_KEY");
export const fn = onRequest({ secrets: [apiKey] }, handler);
אחרי שההרחבה תועבר לחבילת npm או לערכת כלים, ההפניות לסודות ינוהלו בקובץ .env של משתמש הקצה. חשוב לא לשנות את שמות הסודות שמוצהרים בקוד בכלל. במהלך ההעברה, הסודות של משתמשי הקצה יועברו בהתאם.
דוגמה: שליחת אימייל מ-Cloud Firestore
לפני. המשתנים MAIL_COLLECTION ו-SMTP_PASSWORD נקראים כמשתני סביבה גולמיים בקובץ config.ts:
# extension.yaml
- param: MAIL_COLLECTION
label: Email documents collection
type: string
default: mail
required: true
- param: SMTP_PASSWORD
label: SMTP password
type: secret
// functions/src/config.ts
mailCollection: process.env.MAIL_COLLECTION,
smtpPassword: process.env.SMTP_PASSWORD,
אחרי. defineString אחד ו-defineSecret אחד; ה-CLI מאתר את שניהם וקורא מ-.env
import { defineString, defineSecret } from "firebase-functions/params";
import { onDocumentWritten } from "firebase-functions/firestore";
const mailCollection = defineString("MAIL_COLLECTION",{ label: "Email documents collection",
default: "mail"
});
const smtpPassword = defineSecret("SMTP_PASSWORD", { label: "SMTP password" });
export const processQueue = onDocumentWritten(
{ document: `${mailCollection}/{documentId}`, secrets: [smtpPassword] },
async (event) => {
const collection = mailCollection.value();
const password = smtpPassword.value();
// ...
}
);
העברת קריאות פנימיות לתור משימות
חלק מהתוספים מוסיפים עבודות לתורי המשימות שלהם מתוך קוד הפונקציה שלהם, באמצעות Firebase Admin SDK. זה שונה מקבלת משימה שנשלחה (הנושאים האלה מוסברים בקטע שדרוג פונקציות ובקטע המרת ווים של מחזור חיים). הקוד שלכם הוא producer שקורא ל-queue.enqueue(...).
בגרסאות קודמות של Admin SDK, תוספים נדרשו להעביר את מזהה מופע התוסף שלהם כפרמטר שני כדי לטרגט פונקציה של תור משימות באותו תוסף. החל מגרסה 14.2.0 של `firebase-admin`, אין צורך בכך ולא מומלץ לעשות זאת. ה-API של תור המשימות יכוון עכשיו כברירת מחדל לתורי משימות באותו ההקשר (למשל, תוסף). מומלץ להסיר את הפרמטר הזה מהקוד, גם כתוסף וגם כפונקציות עצמאיות. הסרה של הפרמטר הזה מבטיחה ניידות ותאימות קדימה.
כל שאר הפרטים לגבי הקריאה להוספה לתור – נתיב המשאב locations/region/functions/name, מטען הייעודי (payload) של המשימה והלוגיקה של הניסיון החוזר – נשארים ללא שינוי.
פרטים נוספים על הוספת פונקציות לתור באמצעות Cloud Tasks זמינים במאמר /docs/functions/task-functions.
לפני. תוסף דור ראשון
import { getFunctions } from "firebase-admin/functions";
const queue = getFunctions().taskQueue(
`locations/${config.location}/functions/syncBigQuery`,
process.env.EXT_INSTANCE_ID, // extension instance ID, injected by the runtime
);
await queue.enqueue(taskData);
אחרי. תוסף דור שני
import { getFunctions } from "firebase-admin/functions";
import { region } from "firebase-functions/params";
const queue = getFunctions().taskQueue(
`locations/${region.value()}/functions/syncBigQuery`);
await queue.enqueue(taskData);
אם הקריאה לפונקציה enqueue מכוונת לבסיס קוד עם קידומת, גם לשם הפונקציה שמתגלה תתווסף קידומת (לדוגמה, orders-syncBigQuery).
הצהרה על ממשקי API ותפקידים ב-IAM שנדרשים
מעבירים את דרישות ה-IAM וה-API של התוסף מ-extension.yaml אל code:
import { requiresAPI, requiresRole } from "firebase-functions"
requiresAPI("bigquery.googleapis.com", "Needed to write changelog rows");
requiresRole("roles/bigquery.dataEditor");
requiresRole("roles/bigquery.user");
באמצעות אבטחה הצהרתית, ה-CLI של Firebase יוצר או מעדכן חשבון שירות מנוהל של זמן ריצה עבור בסיס הקוד, ומעניק לו את כל התפקידים שהוגדרו. צריך לציין למשתמשים שכל הפונקציות בבסיס הקוד פועלות עם התפקידים האלה, אלא אם ה-API הסופי תומך במודל מצומצם יותר.
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
לפני. ההצהרה מופיעה בקובץ extension.yaml. זמן הריצה של התוספים הפעיל את ה-API והעניק את התפקידים לחשבון מנוהל:
apis:
- apiName: bigquery.googleapis.com
roles:
- role: bigquery.dataEditor
- role: datastore.user
- role: bigquery.user
אחרי. מוצהר בקוד באמצעות requiresAPI ו-requiresRole:
import { requiresAPI, requiresRole } from "firebase-functions/";
requiresAPI("bigquery.googleapis.com",
"Needed to write changelog rows and views");
requiresRole("roles/biguqery.dataEditor");
requiresRole("roles/datastore.user");
requiresRole("roles/bigquery.user");
המרת טיזרים של מחזור חיים
לדוגמה, אם התוסף קורא ל-getExtensions().runtime(), ל-setProcessingState או ל-setFatalError, צריך למחוק את הקריאות האלה, כי אם הן יתבצעו מפונקציה מהדור השני שנפרסה כרגיל, תוצג שגיאה. מצב מחזור החיים מבוסס עכשיו על afterFirstDeploy ו-afterRedeploy במקרים שבהם לא נעשה שימוש במעקב אחרי המצב הזה.
Firebase Extensions יכול להפעיל הגדרה כשמשתמש מתקין, מעדכן או מגדיר מחדש תוסף. בחבילת npm, צריך להצהיר על פעולות מחזור חיים מקבילות בקוד.
כדי להגדיר את האפליקציה בפעם הראשונה:
import { afterFirstDeploy } from "firebase-functions/lifecycle";
import { onTaskDispatched } from "firebase-functions/tasks";
export const runInitialSetup = onTaskDispatched(async (request) => {
await initializeResources(request.data);
});
afterFirstDeploy({
task: {
function: "runInitialSetup",
body: {}
}
});
לעדכוני קוד או הגדרות:
import { afterRedeploy } from "firebase-functions/lifecycle";
afterRedeploy({
task: {
function: "runInitialSetup",
body: { reconcile: true }
}
});
הופכים את הפעולות במחזור החיים לאידמפוטנטיות. יכול להיות שהמשתמשים יצטרכו להריץ אותם מחדש באופן ידני אם השליחה או ההפעלה ייכשלו:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME
firebase functions:lifecycle:run afterRedeploy CODEBASE_NAME
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
לפני. lifecycleEvents ב-extension.yaml, מופעל על ידי זמן הריצה של התוספים:
lifecycleEvents:
onInstall:
function: initBigQuerySync
processingMessage: Configuring BigQuery Sync.
onUpdate:
function: setupBigQuerySync
processingMessage: Configuring BigQuery Sync
onConfigure:
function: setupBigQuerySync
processingMessage: Configuring BigQuery Sync
אחרי. מוצהר בקוד; המשימה מספקת BigQuery בפריסה הראשונה:
import { afterFirstDeploy, afterRedeploy } from "firebase-functions/lifecycle";
afterFirstDeploy({ task: { function: "initBigQuerySync" } });
afterRedeploy({ task: { function: "setupBigQuerySync" } });
הקצאת הרשאות היא אידמפוטנטית, ולכן הפעלה חוזרת מתקנת את מערך הנתונים, הטבלה והתצוגות. המשתמשים יכולים להפעיל מחדש באופן ידני באמצעות firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME.
הגדרת מסמכים למשתמשים
כותבים
READMEשל חבילה שכולל לפחות את הפרטים הבאים:הערכים של
.envשהחבילה דורשת.הסודות שנדרשים לחבילה, ואיך להעביר ערכי סודות קיימים.
תפקידי ה-IAM שהחבילה מצהירה עליהם באמצעות
requiresRole(...).ממשקי Google API שהחבילה מפעילה או שנדרשים להפעלה.
ה-lifecycle hooks שהחבילה מצהירה עליהם, ואיך להריץ אותם מחדש באופן ידני.
הערות לגבי חיובים.
מה השתנה בהשוואה לתוסף המקורי.
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
קובץ ה-README של החבילה כולל טבלה קונקרטית עם פירוט השינויים:
| סוג הטיפול | כתוסף | As @firebase/firestore-bigquery-export |
|---|---|---|
| הגדרה | פרמטרים של תוספים | פרמטרים של פונקציות דרך .env |
| IAM | ההרשאה ניתנה על ידי Extensions | requiresRole(...), applied at deploy |
| ניהול הקצאות (Provisioning) | משימה במחזור החיים באמצעות Extensions | משימה afterFirstDeploy / afterRedeploy |
| שמות הפונקציות | ext-instanceId-fsexportbigquery | fsexportbigquery (עם קידומת אופציונלית) |
בדיקת פונקציה מדור שני
עכשיו אמורה להיות לכם פונקציה מדור שני, שכשתפרסו אותה, היא תתנהג בדיוק כמו התקנה חדשה של התוסף. השלב האחרון הוא לאמת ולתקן בעיות שנוצרו בטעות במהלך התהליך.
חשוב לוודא שאתם משתמשים ב-firebase-tools בגרסה >= 15.24.0, ומבצעים פריסה של הפונקציה שהומרה מדור שני לפרויקט בדיקה עם המשאבים המתאימים כדי לבדוק את ההתנהגות שלה. אם כבר הגדרתם פרויקט בדיקה כדי לבדוק את התוסף, משתמשים בפקודה:
firebase deploy --only functions
אחרי שמזינים את הפקודה הזו, ממלאים את האשף שמופיע עם ערכי הפרמטרים, בדיוק כמו שממלאים את טופס ההתקנה במסוף Firebase של התוסף.
דוגמה מעשית: העברת נתונים מ-Firestore ל-BigQuery
אנחנו מאמתים את הסנכרון מקצה לקצה של Cloud Firestore ל-BigQuery:
- במסוף Cloud Firestore, יוצרים את האוסף שהגדרתם כ-COLLECTION_PATH (משתמשים) אם הוא עדיין לא קיים.
- יוצרים מסמך בשם bigquery-mirror-test שמכיל שדות עם ערכים כלשהם.
- במסוף BigQuery, מריצים שאילתה על טבלת יומן השינויים הגולמי. הוא צריך להכיל שורה אחת שמתעדת את יצירת המסמך:
SELECT * FROM `PROJECT_ID.analytics.users_raw_changelog`
- מריצים שאילתה על התצוגה האחרונה, שאמורה להחזיר את אירוע השינוי האחרון עבור המסמך היחיד שקיים:
bigquery-mirror-test
SELECT * FROM `PROJECT_ID.analytics.users_raw_latest`
- מוחקים את המסמך
bigquery-mirror-testב-Cloud Firestore. הוא נעלם מהתצוגה האחרונה, ואירועDELETEמצורף לטבלת יומן השינויים הגולמי.
אפשר לבדוק את ההיסטוריה המלאה של מסמך יחיד באמצעות:
SELECT *
FROM `PROJECT_ID.analytics.users_raw_changelog`
WHERE document_name = "bigquery-mirror-test"
ORDER BY timestamp ASC
ההבדלים מבדיקת התוסף:
- הטריגר נפרס כ-
fsexportbigquery(אפשר להוסיף קידומת של בסיס הקוד), ולא כ-ext-<instanceId>-fsexportbigquery. מחפשים את השם הזה בלוח הבקרה וברישומים.Cloud Functions - הקוד יפעל עכשיו ב-Firebase Local Emulator Suite כפונקציות רגילות. אפשר להגדיר את ערך הפרמטרים לשימוש באמולטור באמצעות
.env.local. אפשר גם לבצע בדיקות יחידה של הקוד באמצעות firebase-functions-test SDK, כמו שמתואר במאמר בדיקות יחידה של Cloud Functions - הקצאת ההרשאות כבר לא מתבצעת על ידי זמן הריצה של התוספים. אם טבלת יומן השינויים
חסרה אחרי הפריסה, מריצים מחדש את משימת ההגדרה באופן ידני:
firebase functions:lifecycle:run afterFirstDeploy CODEBASE_NAME. המשימה היא אידמפוטנטית, ולכן הפעלה חוזרת שלה תתאים בין מערך הנתונים, הטבלה והתצוגות. - ערכי הפרמטרים מגיעים מ-
.envולא מטופס ההתקנה, ולכן הפעלות חוזרות שלfirebase deployלא אינטראקטיביות אחרי ש-.envמסתיים.