على التطبيقات التي تستخدِم دوال الجيل الأول التفكير في نقل البيانات إلى الجيل الثاني باستخدام التعليمات الواردة في هذا الدليل. تستخدِم دوال الجيل الثاني Cloud Run لتقديم أداء أفضل وإعدادات أفضل ومراقبة أفضل والمزيد.
تفترض الأمثلة الواردة في هذه الصفحة أنّك تستخدِم JavaScript مع وحدات CommonJS (عمليات الاستيراد بنمط require)، ولكن تنطبق المبادئ نفسها على JavaScript مع وحدات ESM (عمليات الاستيراد بنمط import … from) وTypeScript.
عملية نقل البيانات
يمكن أن تتعايش دوال الجيل الأول والجيل الثاني جنبًا إلى جنب في الملف نفسه. يسمح ذلك بنقل البيانات بسهولة جزءًا جزءًا، عندما تكون مستعدًا. ننصح بنقل دالة واحدة في كل مرة، وإجراء الاختبار والتحقّق قبل المتابعة.
التحقّق من إصدارات Firebase CLI وfirebase-function
تأكَّد من استخدام الإصدار 12.00 على الأقل من Firebase CLI والإصدار 4.3.0 من firebase-functions. سيتوافق أي إصدار أحدث مع الجيل الثاني والجيل الأول.
تعديل عمليات الاستيراد
تستورد دوال الجيل الثاني من الحزمة الفرعية v2 في حزمة تطوير البرامج (SDK) الخاصة بـ firebase-functions.
إنّ مسار الاستيراد المختلف هو كل ما يحتاج إليه Firebase CLI لتحديد ما إذا كان سيتم نشر رمز الدالة البرمجية كدالة من الجيل الأول أو الجيل الثاني.
الحزمة الفرعية v2 هي حزمة نمطية، وننصحك باستيراد الوحدة النمطية المحدّدة التي تحتاج إليها فقط.
قبل: الجيل الأول
const functions = require("firebase-functions/v1");
بعد: الجيل الثاني
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
تعديل تعريفات المشغّلات
بما أنّ حزمة تطوير البرامج (SDK) الخاصة بالجيل الثاني تفضّل عمليات الاستيراد النمطية، عدِّل تعريفات المشغّلات لتعكس عمليات الاستيراد التي تم تغييرها من الخطوة السابقة.
تغيّرت الوسيطات التي يتم تمريرها إلى عمليات معاودة الاتصال لبعض المشغّلات. في هذا المثال، يُرجى العِلم بأنّه تم دمج وسيطات معاودة الاتصال onDocumentCreated في عنصر event واحد. بالإضافة إلى ذلك، تتضمّن بعض المشغّلات ميزات إعداد جديدة ومريحة، مثل خيار cors في المشغّل onRequest.
قبل: الجيل الأول
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
بعد: الجيل الثاني
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
استخدام الإعدادات المزوّدة بمَعلمات
تتوقّف دوال الجيل الثاني عن دعم functions.config لصالح واجهة أكثر أمانًا
لتحديد مَعلمات الإعداد بشكلٍ تصريحي
داخل قاعدة التعليمات البرمجية.
باستخدام الوحدة النمطية الجديدة params، يحظر Firebase CLI عملية النشر ما لم يكن لجميع المَعلمات قيمة صالحة، ما يضمن عدم نشر دالة بدون إعدادات.
قبل: الجيل الأول
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
بعد: الجيل الثاني
const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");
// Define the secret parameter
const apiKey = defineSecret("API_KEY");
exports.getQuote = onRequest(
// make the secret available to this function
{ secrets: [apiKey] },
async (req, res) => {
// retrieve the value of the secret
const quote = await fetchMotivationalQuote(apiKey.value());
// ...
}
);
إذا كان لديك إعداد حالي للبيئة باستخدام functions.config، يمكنك نقل هذا الإعداد كجزء من الترقية إلى الجيل الثاني.
تم إيقاف واجهة برمجة التطبيقات functions.config نهائيًا وسيتم إيقافها في مارس 2027.
بعد هذا التاريخ، ستفشل عمليات النشر باستخدام functions.config.
لمنع حالات فشل النشر، يمكنك نقل الإعدادات إلى Cloud Secret Manager باستخدام Firebase CLI. ننصح بشدة باستخدام هذه الطريقة لأنّها الطريقة الأكثر فعالية وأمانًا لنقل الإعدادات.
تصدير الإعدادات باستخدام Firebase CLI
استخدِم الأمر
config exportلتصدير إعدادات البيئة الحالية إلى سر جديد في Cloud Secret Manager:$ firebase functions:config:export i This command retrieves your Runtime Config values (accessed via functions.config()) and exports them as a Secret Manager secret. i Fetching your existing functions.config() from your project... ✔ Fetched your existing functions.config(). i Configuration to be exported: ⚠ This may contain sensitive data. Do not share this output. { ... } ✔ What would you like to name the new secret for your configuration? RUNTIME_CONFIG ✔ Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```تعديل رمز الدالة البرمجية لربط الأسرار
لاستخدام الإعدادات المخزّنة في السر الجديد في Cloud Secret Manager، استخدِم واجهة برمجة التطبيقات
defineJsonSecretفي مصدر الدالة. تأكَّد أيضًا من ربط الأسرار بجميع الدوال التي تحتاج إليها.قبل
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });بعد
const { onRequest } = require("firebase-functions/v2/https"); const { defineJsonSecret } = require("firebase-functions/params"); const config = defineJsonSecret("RUNTIME_CONFIG"); exports.myFunction = onRequest( // Bind secret to your function { secrets: [config] }, (req, res) => { // Access secret values via .value() const apiKey = config.value().someapi.key; // ... });تفعيل الوظائف
انشر الدوال المعدَّلة لتطبيق التغييرات وربط أذونات السر.
firebase deploy --only functions:<your-function-name>
ضبط خيارات وقت التشغيل
تغيّرت إعدادات خيارات وقت التشغيل بين الجيل الأول والجيل الثاني. يضيف الجيل الثاني أيضًا إمكانية جديدة لـ ضبط الخيارات لجميع الدوال.
قبل: الجيل الأول
const functions = require("firebase-functions/v1");
exports.date = functions
.runWith({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
})
// locate function closest to users
.region("asia-northeast1")
.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions
// locate function closest to users and database
.region("asia-northeast1")
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
بعد: الجيل الثاني
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");
// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });
exports.date = onRequest({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
تعديل حساب الخدمة التلقائي (اختياري)
بينما تستخدِم دوال الجيل الأول حساب الخدمة التلقائي في Google App Engine لتخويل الوصول إلى واجهات برمجة تطبيقات Firebase، تستخدِم دوال الجيل الثاني حساب الخدمة التلقائي في Compute Engine. يمكن أن يؤدي هذا الاختلاف إلى حدوث مشاكل في الأذونات للدوال التي تم نقلها إلى الجيل الثاني في الحالات التي منحت فيها أذونات خاصة لحساب خدمة الجيل الأول. إذا لم تغيِّر أي أذونات لحساب الخدمة، يمكنك تخطّي هذه الخطوة.
الحل المقترَح هو تعيين حساب الخدمة التلقائي الحالي في App Engine للجيل الأول بشكلٍ صريح للدوال التي تريد نقلها إلى الجيل الثاني، ما يؤدي إلى إلغاء حساب الخدمة التلقائي للجيل الثاني. يمكنك إجراء ذلك من خلال التأكّد من أنّ كل دالة تم نقلها تضبط القيمة الصحيحة لـ serviceAccountEmail:
const {onRequest} = require("firebase-functions/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions");
// Use the App Engine default service account for all functions
setGlobalOptions({serviceAccountEmail: '<my-project-number>@<wbr>appspot.gserviceaccount.com'});
// Now I use the App Engine default service account.
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
// I do too!
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
// ...
});
بدلاً من ذلك، يمكنك التأكّد من تعديل تفاصيل حساب الخدمة لتتطابق مع جميع الأذونات اللازمة على كلٍّ من حساب الخدمة التلقائي في App Engine (للجيل الأول) وحساب الخدمة التلقائي في Compute Engine (للجيل الثاني).
استخدام التزامن
من المزايا المهمة لدوال الجيل الثاني قدرة مثيل دالة واحد على معالجة أكثر من طلب واحد في الوقت نفسه. يمكن أن يقلّل ذلك بشكلٍ كبير عدد عمليات البدء البارد التي يواجهها المستخدمون النهائيون. يتم ضبط التزامن تلقائيًا على 80، ولكن يمكنك ضبطه على أي قيمة من 1 إلى 1000:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
يمكن أن يؤدي ضبط التزامن إلى تحسين الأداء وتقليل تكلفة الدوال. مزيد من المعلومات حول التزامن في مقالة السماح بالطلبات المتزامنة
مراجعة استخدام المتغيّرات العمومية
قد تستخدِم دوال الجيل الأول التي تمّت كتابتها بدون مراعاة التزامن متغيّرات عمومية يتم ضبطها وقراءتها في كل طلب. عند تفعيل التزامن وبدء مثيل واحد في معالجة طلبات متعددة في الوقت نفسه، قد يؤدي ذلك إلى حدوث أخطاء في الدالة لأنّ الطلبات المتزامنة تبدأ في ضبط المتغيّرات العمومية وقراءتها في الوقت نفسه.
أثناء الترقية، يمكنك ضبط وحدة المعالجة المركزية للدالة على gcf_gen1 وضبط concurrency على 1 لاستعادة سلوك الجيل الأول:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
ومع ذلك، لا يُنصح بذلك كحل طويل الأمد، لأنّه يؤدي إلى فقدان مزايا الأداء لدوال الجيل الثاني. بدلاً من ذلك، راجِع استخدام المتغيّرات العمومية في الدوال، وأزِل هذه الإعدادات المؤقتة عندما تكون مستعدًا.
نقل الزيارات إلى دوال الجيل الثاني الجديدة
تمامًا كما هو الحال عند تغيير منطقة الوظيفة أو نوع المشغّل، عليك منح دالة الجيل الثاني اسمًا جديدًا ونقل الزيارات إليها ببطء.
لا يمكن ترقية دالة من الجيل الأول إلى الجيل الثاني بالاسم نفسه وتشغيل firebase deploy. سيؤدي ذلك إلى ظهور الخطأ التالي:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
قبل اتّباع هذه الخطوات، تأكَّد أولاً من أنّ الدالة غير قابلة للتغيير، لأنّ كلاً من الإصدار الجديد والإصدار القديم من الدالة سيتم تشغيلهما في الوقت نفسه أثناء التغيير. على سبيل المثال، إذا كان لديك دالة من الجيل الأول تستجيب لأحداث الكتابة في Firestore، تأكَّد من أنّ الاستجابة لعملية كتابة مرّتين، مرة واحدة من خلال دالة الجيل الأول ومرة واحدة من خلال دالة الجيل الثاني، استجابةً لتلك الأحداث، تترك تطبيقك في حالة متّسقة.
- أعِد تسمية الدالة في رمز الدوال البرمجية. على سبيل المثال، أعِد تسمية
resizeImageإلىresizeImageSecondGen. - انشر الدالة، بحيث يتم تشغيل كلٍّ من دالة الجيل الأول الأصلية ودالة الجيل الثاني.
- في حالة المشغّلات القابلة للاستدعاء ومشغّلات "قائمة المهام" ومشغّلات HTTP، ابدأ بتوجيه جميع العملاء إلى دالة الجيل الثاني من خلال تعديل رمز العميل البرمجي باسم دالة الجيل الثاني أو عنوان URL الخاص بها.
- باستخدام المشغّلات في الخلفية، ستستجيب كلٌّ من دالة الجيل الأول ودالة الجيل الثاني لكل حدث فور النشر.
- عند نقل جميع الزيارات، احذف دالة الجيل الأول باستخدام الأمر
firebase functions:deleteفي firebase CLI.- اختياريًا، أعِد تسمية دالة الجيل الثاني لتتطابق مع اسم دالة الجيل الأول.