ترقية وظائف Node.js من الجيل الأول إلى الجيل الثاني

على التطبيقات التي تستخدم وظائف الجيل الأول حاليًا الانتقال إلى الجيل الثاني. باستخدام التعليمات الواردة في هذا الدليل. تستخدم دوال الجيل الثاني Cloud Run لتوفير وأداء أفضل، وإعدادات أفضل، ومراقبة أفضل، والمزيد.

تفترض الأمثلة في هذه الصفحة أنّك تستخدم JavaScript مع وحدات CommonJS. (عمليات استيراد نمط require)، ولكن تنطبق المبادئ نفسها على JavaScript مع ESM (عمليات استيراد نمط import … from) وTypeScript.

عملية النقل

يمكن أن تعمل وظيفتا الجيل الأول والجيل الثاني جنبًا إلى جنب في الملف نفسه. هذا النمط تسمح بالهجرة بسهولة على مراحل، عندما تكون مستعدًا. ننصحك بما يلي: نقل دالة واحدة في كل مرة، وإجراء الاختبار والتحقق قبل المتابعة.

التحقّق من إصدار واجهة سطر الأوامر (CLI) في Firebase وإصدارات firebase-function

يُرجى التأكّد من استخدام الإصدار 12.00 من واجهة سطر الأوامر على الأقل من Firebase الإصدار 4.3.0 من firebase-functions ويدعم أي إصدار أحدث الجيل الثاني بالإضافة إلى الجيل الأول

تعديل عمليات الاستيراد

يتم استيراد دوال الجيل الثاني من الحزمة الفرعية v2 في حزمة تطوير البرامج (SDK) firebase-functions. وهذا المسار المختلف للاستيراد هو كل ما يحتاج إليه واجهة سطر الأوامر في Firebase لتحديد ما إذا كان لنشر رمز الدالة كدالة من الجيل الأول أو الثاني.

إنّ الحزمة الفرعية v2 مفصَّلة، وننصحك باستيراد الحزمة الفرعية التي تحتاجها.

قبل: الجيل الأول

const functions = require("firebase-functions");

بعد: الجيل الثاني

// 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");

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 الجديدة، سيحظر واجهة سطر الأوامر (CLI) النشر ما لم تكن جميع المَعلمات ذات قيمة صالحة، ما يضمن عدم نشر الدالة بدون ضبط الإعدادات.

نقل البيانات إلى حزمة "params" الفرعية

إذا كنت تستخدم إعدادات البيئة من خلال functions.config، عليك يمكنك ترحيل التهيئة الحالية إلى الإعداد المضبوط على مَعلمات.

قبل: الجيل الأول

const functions = require("firebase-functions");

exports.date = functions.https.onRequest((req, res) => {
  const date = new Date();
  const formattedDate =
date.toLocaleDateString(functions.config().dateformat);

  // ...
});

بعد: الجيل الثاني

const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");

const dateFormat = defineString("DATE_FORMAT");

exports.date = onRequest((req, res) => {
  const date = new Date();
  const formattedDate = date.toLocaleDateString(dateFormat.value());

  // ...
});

ضبط قيم المَعلمات

عند النشر لأول مرة، يطلب واجهة سطر الأوامر في Firebase عرض جميع قيم وحفظ القيم في ملف dotenv. لتصدير ، قم بتشغيل firebase functions:config:export.

لتوفير مزيد من الأمان، يمكنك أيضًا تحديد أنواع المَعلمات وقواعد التحقّق.

حالة خاصة: مفاتيح واجهة برمجة التطبيقات

يمكن دمج وحدة params مع Cloud Secret Manager الذي يوفّر التحكم في الوصول الدقيق إلى القيم الحساسة مثل مفاتيح واجهة برمجة التطبيقات. عرض المَعلمات السرية لمزيد من المعلومات.

قبل: الجيل الأول

const functions = require("firebase-functions");

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());
    // ...
  }
);

ضبط خيارات بيئة التشغيل

ضبط خيارات بيئة التشغيل بين الجيل الأول والثاني. الجيل الثاني يضيف أيضًا قدرة جديدة إلى وتعيين الخيارات لجميع الدوال.

قبل: الجيل الأول

const functions = require("firebase-functions");

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) => {
  /* ... */
});

استخدام التزامن

من الخصائص المهمة لدوال الجيل الثاني قدرة دالة واحدة حالة لتقديم أكثر من طلب في وقت واحد. يمكن أن يقلل ذلك بشكل كبير عدد عمليات التشغيل على البارد التي واجهها المستخدمون النهائيون. بشكل افتراضي، تكون التزامن على 80، ولكن يمكنك تعيينها على أي قيمة من 1 إلى 1000:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // set concurrency value
    concurrency: 500
  },
  (req, res) => {
    // ...
});

يمكن أن يؤدي ضبط التزامن إلى تحسين الأداء وتقليل تكلفة الوظائف. يمكنك الاطّلاع على مزيد من المعلومات حول التوافق في مقالة السماح بالطلبات المتزامنة.

تدقيق استخدام المتغير العمومي

قد تستخدم دوال الجيل الأول المكتوبة بدون تزامن متغيّرات عمومية. يتم تعيينها وقراءتها عند كل طلب. عند تمكين التزامن بدء معالجة طلبات متعددة في وقت واحد، فقد يتسبب هذا في حدوث أخطاء في الدالة حيث تبدأ الطلبات المتزامنة في إعداد وقراءة المتغيرات العمومية في الوقت نفسه.

أثناء الترقية، يمكنك ضبط وحدة المعالجة المركزية (CPU) للوظيفة على 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، تأكَّد من أنّ الاستجابة لكتابة الأحداث في Firestore مرتَين، مرة عن طريق وظيفة من الجيل الأول ومرة من خلال وظيفة من الجيل الثاني، استجابة لتلك الأحداث، يترك التطبيق تطبيقك في حالة متسقة.

  1. أعد تسمية الدالة في رمز الدوال. على سبيل المثال، أعِد تسمية resizeImage إلى resizeImageSecondGen.
  2. انشر الدالة حتى تعمل وظيفة الجيل الأول الأصلية ودالة الجيل الثاني.
    1. في حال مشغِّلات HTTP و"قائمة انتظار المهام" و"القابلة للاستدعاء"، ابدأ بتوجيه جميع العملاء إلى دالة الجيل الثاني من خلال تعديل رمز العميل باستخدام اسم أو عنوان URL لدالة الجيل الثاني.
    2. من خلال عمليات التشغيل في الخلفية، ستستجيب دالتا الجيل الأول والجيل الثاني لكل حدث فور النشر.
  3. عند إيقاف تشغيل جميع الزيارات، احذف دالة الجيل الأول باستخدام أمر firebase functions:delete في firebase CLI.
    1. اختياريًا، يمكنك إعادة تسمية دالة الجيل الثاني لتطابق اسم دالة الجيل الأول.