البدء: كتابة الدوال الأولى واختبارها ونشرها


لبدء استخدام Cloud Functions، جرِّب العمل من خلال هذا البرنامج التعليمي، الذي يبدأ بمهام الإعداد المطلوبة ويعمل على إنشاء دالتَين مرتبطتَين واختبارهما ونشره:

  • دالة "إضافة رسالة" تعرض عنوان URL يقبل قيمة نصية ويكتبها في Cloud Firestore.
  • دالة "make uppercase" التي يتم تفعيلها عند كتابة Cloud Firestore وتحوِّل النص إلى أحرف كبيرة

في ما يلي نموذج الرمز البرمجي الكامل الذي يحتوي على الدوالّ:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()


@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")


@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

لمحة عن هذا البرنامج التعليمي

لقد اخترنا Cloud Firestore والدوالّ التي يتم تشغيلها من خلال HTTP لهذا المثال، ويعود السبب جزئيًا إلى أنّه يمكن اختبار عوامل التفعيل هذه في الخلفية بشكل كامل من خلال Firebase Local Emulator Suite. تتيح مجموعة الأدوات هذه أيضًا استخدام Realtime Database وCloud Storage وPubSub وAuth وHTTP للتشغيل المُستدعى. يمكن اختبار الأنواع الأخرى من عوامل التفعيل التي تعمل في الخلفية، مثل عوامل التفعيل في Remote Config وTestLab، بشكل تفاعلي باستخدام مجموعات أدوات غير описанة في هذه الصفحة.

توضح الأقسام التالية من هذا البرنامج التعليمي بالتفصيل الخطوات المطلوبة لإنشاء النموذج واختباره ونشره.

إنشاء مشروع على Firebase

  1. في وحدة تحكّم Firebase، انقر على إضافة مشروع.

    • لإضافة موارد Firebase إلى مشروع Google Cloud حالي، أدخِل اسم المشروع أو اختَره من القائمة المنسدلة.

    • لإنشاء مشروع جديد، أدخِل اسم المشروع المطلوب. يمكنك أيضًا تعديل رقم تعريف المشروع المعروض أسفل اسم المشروع اختياريًا.

  2. راجِع بنود Firebase واقبلها إذا طُلب منك ذلك.

  3. انقر على متابعة.

  4. (اختياري) يمكنك إعداد Google Analytics لمشروعك، ما يتيح لك الحصول على تجربة مثالية باستخدام أيّ من منتجات Firebase التالية:

    اختَر إما حساب Google Analytics حاليًا أو أنشئ حسابًا جديدًا.

    إذا أنشأت حسابًا جديدًا، اختَر Analytics الموقع الجغرافي لإعداد التقارير، ثم وافِق على إعدادات مشاركة البيانات وبنود Google Analytics لمشروعك.

  5. انقر على إنشاء مشروع (أو إضافة Firebase، إذا كنت تستخدم مشروعًا حاليًا على Google Cloud).

توفّر Firebase الموارد تلقائيًا لمشروعك على Firebase. عند اكتمال العملية، سيتم نقلك إلى صفحة النظرة العامة الخاصة بمشروع Firebase في وحدة تحكّم Firebase.

إعداد بيئتك وواجهة Firebase CLI

Node.js

ستحتاج إلى بيئة Node.js لكتابة الدوال، وستحتاج إلى واجهة برمجة التطبيقات Firebase لنشر الدوال إلى وقت تشغيل Cloud Functions. لتثبيت Node.js وnpm،ننصح باستخدام Node Version Manager .

بعد تثبيت Node.js وnpm، ثبِّت Firebase CLI باستخدام الطريقة المفضّلة لديك. لتثبيت واجهة سطر الأوامر من خلال npm، استخدِم:

npm install -g firebase-tools

يؤدي ذلك إلى تثبيت أمر firebase المتاح على مستوى العالم. إذا تعذّر تنفيذ الأمر، قد تحتاج إلى تغيير أذونات npm. لتحديث أحدث إصدار من firebase-tools، يُرجى إعادة تنفيذ الأمر نفسه.

Python

ستحتاج إلى بيئة Python لكتابة الدوال، وستحتاج إلى واجهة برمجة التطبيقات Firebase لنشر الدوال في IDE Cloud Functions. ننصح باستخدام venv لمحاولة عزل التبعيات. الإصداران 3.10 و3.11 من Python متوافقان.

بعد تثبيت لغة Python، ثبِّت واجهة سطر الأوامر Firebase من خلال طريقتك المفضّلة.

بدء مشروعك

عند إعداد حزمة SDK لنظام التشغيل Firebase على نظام التشغيل Cloud Functions، يتم إنشاء مشروع فارغ يحتوي على التبعيات وبعض النماذج البسيطة للرموز البرمجية. إذا كنت تستخدم Node.js، يمكنك اختيار إما TypeScript أو JavaScript لإنشاء الدوالّ. لأغراض هذا الدليل التمهيدي، عليك أيضًا إعداد Cloud Firestore.

لبدء مشروعك:

  1. شغِّل firebase login لتسجيل الدخول من خلال المتصفّح ومصادقة Firebase CLI.
  2. انتقِل إلى دليل مشروعك على Firebase.
  3. شغِّل firebase init firestore. في هذا البرنامج التعليمي، يمكنك قبول القيم التلقائية عندما يُطلب منك إدخال قواعد Firestore وملفات الفهرسة. إذا لم يسبق لك استخدام Cloud Firestore في هذا المشروع، عليك أيضًا اختيار وضع البدء وموقع Firestore كما هو موضّح في البدء باستخدام Cloud Firestore.
  4. تشغيل firebase init functions تطلب منك واجهة برمجة التطبيقات اختيار قاعدة رمز برمجي حالية أو بدء قاعدة جديدة وتسميتها. عندما تبدأ للتو، يكفي توفّر قاعدة رموز برمجية واحدة في الموقع التلقائي. في وقت لاحق، مع توسيع عملية التنفيذ، قد تريد تنظيم الدوال في قواعد الرموز.
  5. تمنحك واجهة برمجة التطبيقات هذه الخيارات لتوفير الدعم اللغوي:

    • JavaScript
    • TypeScript
    • Python

    في هذا الدليل التعليمي، اختَر JavaScript أو Python. لإنشاء المحتوى باستخدام TypeScript، اطّلِع على مقالة كتابة الدوال باستخدام TypeScript.

  6. تمنحك واجهة برمجة التطبيقات خيار تثبيت التبعيات. يمكنك بأمان رفض هذا الخيار إذا كنت تريد إدارة التبعيات بطريقة أخرى.

بعد اكتمال هذه الأوامر بنجاح، ستظهر بنية مشروعك على النحو التالي:

Node.js

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- .eslintrc.json  # Optional file containing rules for JavaScript linting.
      |
      +- package.json  # npm package file describing your Cloud Functions code
      |
      +- index.js      # Main source file for your Cloud Functions code
      |
      +- node_modules/ # Directory where your dependencies (declared in
                        # package.json) are installed

بالنسبة إلى Node.js، يحتوي ملف package.json الذي تم إنشاؤه أثناء الإعداد على مفتاح مهم: "engines": {"node": "18"}. يحدِّد هذا الخيار إصدار Node.js لكتابة الدوالّ ونشرها. يمكنك اختيار إصدارات أخرى متوافقة.

Python

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
      |
      +- main.py      # Main source file for your Cloud Functions code
      |
      +- requirements.txt  #  List of the project's modules and packages 
      |
      +- venv/ # Directory where your dependencies are installed

استيراد الوحدات المطلوبة وبدء تطبيق

بعد الانتهاء من مهام الإعداد، يمكنك فتح الدليل المصدر والبدء في إضافة الرمز كما هو مُوضَّح في الأقسام التالية. في هذا العيّنة، يجب أن يستورد مشروعك وحدتَي IDE Cloud Functions وAdmin SDK. أضِف أسطرًا مثل ما يلي إلى ملف المصدر:

Node.js

// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const {logger} = require("firebase-functions");
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");

// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const {getFirestore} = require("firebase-admin/firestore");

initializeApp();

Python

# The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
from firebase_functions import firestore_fn, https_fn

# The Firebase Admin SDK to access Cloud Firestore.
from firebase_admin import initialize_app, firestore
import google.cloud.firestore

app = initialize_app()

تُحمِّل هذه الأسطر الوحدات المطلوبة وتضبط مثيل تطبيق admin الذي يمكن إجراء تغييرات Cloud Firestore منه. في أيّ مكان تتوفّر فيه إمكانية استخدام حزمة تطوير البرامج (SDK) الخاصة بالمسؤولين، كما هو الحال في FCM وAuthentication وFirebase Realtime Database، توفّر هذه الحزمة طريقة فعّالة لدمج Firebase باستخدام Cloud Functions.

تثبِّت أداة Firebase CLI تلقائيًا حزمة تطوير البرامج (SDK) لخدمة "Firebase Admin SDK" وحزمة Firebase SDK لمكوّنات Cloud Functions عند بدء مشروعك. لمزيد من المعلومات عن إضافة مكتبات تابعة لجهات خارجية إلى مشروعك، يُرجى الاطّلاع على معالجة التبعيات.

إضافة الدالة add message

بالنسبة إلى الدالة add message، أضِف الأسطر التالية إلى ملف المصدر:

Node.js

// Take the text parameter passed to this HTTP endpoint and insert it into
// Firestore under the path /messages/:documentId/original
exports.addmessage = onRequest(async (req, res) => {
  // Grab the text parameter.
  const original = req.query.text;
  // Push the new message into Firestore using the Firebase Admin SDK.
  const writeResult = await getFirestore()
      .collection("messages")
      .add({original: original});
  // Send back a message that we've successfully written the message
  res.json({result: `Message with ID: ${writeResult.id} added.`});
});

Python

@https_fn.on_request()
def addmessage(req: https_fn.Request) -> https_fn.Response:
    """Take the text parameter passed to this HTTP endpoint and insert it into
    a new document in the messages collection."""
    # Grab the text parameter.
    original = req.args.get("text")
    if original is None:
        return https_fn.Response("No text parameter provided", status=400)

    firestore_client: google.cloud.firestore.Client = firestore.client()

    # Push the new message into Cloud Firestore using the Firebase Admin SDK.
    _, doc_ref = firestore_client.collection("messages").add({"original": original})

    # Send back a message that we've successfully written the message
    return https_fn.Response(f"Message with ID {doc_ref.id} added.")

دالة "إضافة رسالة" هي نقطة نهاية HTTP. يؤدي أي طلب إلى نقطة النهاية إلى إنشاء كائنَي الطلب والاستجابة يتم تمريرهما إلى معالج الطلب لمنصتك (onRequest() أو on_request).

دوال HTTP متزامنة (على غرار الدوال القابلة للاستدعاء)، لذا يجب إرسال استجابة في أسرع وقت ممكن وتأجيل العمل باستخدام Cloud Firestore. تُرسِل دالة HTTP "إضافة رسالة" قيمة نصية إلى نقطة نهاية HTTP وتُدرِجها في قاعدة البيانات ضمن المسار /messages/:documentId/original.

أضِف الدالة make uppercase.

بالنسبة إلى الدالة make uppercase، أضِف الأسطر التالية إلى ملف المصدر:

Node.js

// Listens for new messages added to /messages/:documentId/original
// and saves an uppercased version of the message
// to /messages/:documentId/uppercase
exports.makeuppercase = onDocumentCreated("/messages/{documentId}", (event) => {
  // Grab the current value of what was written to Firestore.
  const original = event.data.data().original;

  // Access the parameter `{documentId}` with `event.params`
  logger.log("Uppercasing", event.params.documentId, original);

  const uppercase = original.toUpperCase();

  // You must return a Promise when performing
  // asynchronous tasks inside a function
  // such as writing to Firestore.
  // Setting an 'uppercase' field in Firestore document returns a Promise.
  return event.data.ref.set({uppercase}, {merge: true});
});

Python

@firestore_fn.on_document_created(document="messages/{pushId}")
def makeuppercase(event: firestore_fn.Event[firestore_fn.DocumentSnapshot | None]) -> None:
    """Listens for new documents to be added to /messages. If the document has
    an "original" field, creates an "uppercase" field containg the contents of
    "original" in upper case."""

    # Get the value of "original" if it exists.
    if event.data is None:
        return
    try:
        original = event.data.get("original")
    except KeyError:
        # No "original" field, so do nothing.
        return

    # Set the "uppercase" field.
    print(f"Uppercasing {event.params['pushId']}: {original}")
    upper = original.upper()
    event.data.reference.update({"uppercase": upper})

يتم تنفيذ الدالة make uppercase عند الكتابة إلى Cloud Firestore، لتحديد المستند الذي سيتم الاستماع إليه. لأسباب تتعلّق بالأداء، يجب أن تكون دقيقًا قدر الإمكان.

تحيط الأقواس، على سبيل المثال {documentId}، بـ "المَعلمات"، وهي العناصر النائبة التي تعرض بياناتها المطابقة في دالة "مكالمة إعادة الاتصال". يؤدي Cloud Firestore إلى بدء الإجراء المُعاد عند إضافة رسائل جديدة.

في Node.js، تكون الدوالّ المستندة إلى الأحداث، مثل أحداث Cloud Firestore، غير متزامنة. يجب أن تعرِض وظيفة ردّ الاتصال إما null أو عنصرًا أو وعدًا. إذا لم يتم عرض أيّ شيء، تنتهي مهلة الدالة، ما يشير إلى حدوث خطأ، ويتم إعادة المحاولة. اطّلِع على Sync وAsync وPromises.

محاكاة تنفيذ دوالّك

تتيح لك Firebase Local Emulator Suite إنشاء التطبيقات واختبارها على جهازك المحلي بدلاً من نشرها في مشروع على Firebase. ننصح بشدة بإجراء الاختبار على الجهاز أثناء التطوير، ويعود السبب في ذلك جزئيًا إلى أنّه يقلل من خطر أخطاء الترميز التي قد تؤدي إلى تحمُّل تكلفة في بيئة الإنتاج (على سبيل المثال، حلقة لا نهائية).

لمحاكاة وظائفك:

  1. شغِّل firebase emulators:start وتحقّق من الناتج لعنوان URL للEmulator Suite UI. الإعداد التلقائي هو localhost:4000، ولكن قد يتم استضافته على منفذ مختلف على جهازك. أدخِل عنوان URL هذا في المتصفّح لفتح Emulator Suite UI.

  2. تحقّق من ناتج الأمر firebase emulators:start لعنوان URL لدالة HTTP. سيبدو مشابهًا لرمز http://localhost:5001/MY_PROJECT/us-central1/addMessage، باستثناء ما يلي:

    1. سيتم استبدال MY_PROJECT بمعرّف مشروعك.
    2. قد يكون المنفذ مختلفًا على جهازك المحلي.
  3. أضِف سلسلة الطلب ?text=uppercaseme إلى نهاية عنوان URL للدالة. من المفترض أن يظهر المحتوى بالشكل التالي: http://localhost:5001/MY_PROJECT/us-central1/addMessage?text=uppercaseme. يمكنك اختياريًا تغيير الرسالة "كبير الأحرف" إلى رسالة مخصّصة.

  4. أنشئ رسالة جديدة من خلال فتح عنوان URL في علامة تبويب جديدة في المتصفّح.

  5. يمكنك الاطّلاع على تأثيرات الدوالّ في Emulator Suite UI:

    1. في علامة التبويب السجلات، من المفترض أن تظهر لك سجلات جديدة تشير إلى إتمام دوال HTTP بنجاح:

      i functions: Beginning execution of "addMessage"

      i functions: Beginning execution of "makeUppercase"

    2. في علامة التبويب Firestore، من المفترض أن يظهر لك مستند يحتوي على رسالتك الأصلية بالإضافة إلى النسخة بأحرف كبيرة من رسالتك (إذا كانت في الأصل "uppercaseme"، ستظهر لك "UPPERCASEME").

نشر الدوال في بيئة إنتاج

بعد أن تعمل الوظائف على النحو المطلوب في المحاكي، يمكنك مواصلة نشرها واختبارها وتشغيلها في بيئة الإنتاج. يُرجى العِلم أنّه للترقية إلى مرحلة الإنتاج، يجب أن يكون مشروعك ضمن خطة أسعار Blaze. اطّلِع على أسعارCloud Functions.

لإكمال البرنامج التعليمي، عليك نشر الدوالّ ثم تنفيذها.

  1. نفِّذ هذا الأمر لنشر دوالّك:

     firebase deploy --only functions
     

    بعد تنفيذ هذا الأمر، تُخرج واجهة سطر أوامر Firebase عنوان URL لأي نقاط نهاية لوظائف HTTP. في الوحدة الطرفية، من المفترض أن يظهر لك سطر مثل ما يلي:

    Function URL (addMessage): https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage
    

    يحتوي عنوان URL على معرّف مشروعك بالإضافة إلى منطقة لوظيفة HTTP . ليس عليك القلق الآن، ولكن يجب أن تحدّد بعض دوال HTTP للإنتاج موقعًا جغرافيًا لتقليل وقت استجابة الشبكة.

    إذا واجهت أخطاء في الوصول مثل "تعذّر تفويض الوصول إلى project"، حاوِل التحقّق من الاسم المعرِّف للمشروع.

  2. باستخدام عنوان URL الذي يعرضه سطر الأوامر، أضِف مَعلمة طلب بحث نصية، ثم افتح عنوان URL في متصفّح:

    https://us-central1-MY_PROJECT.cloudfunctions.net/addMessage?text=uppercasemetoo
    

    تنفِّذ الدالة المتصفّح وتعيد توجيهه إلى Firebase وحدة التحكّم في مكان قاعدة البيانات حيث يتم تخزين سلسلة النصوص. يؤدي حدث الكتابة هذا إلى تنشيط الدالة make uppercase التي تكتب نسخة بالأحرف اللاتينية الكبيرة من السلسلة.

بعد نشر الدوال وتنفيذها، يمكنك الاطّلاع على السجلات في وحدة تحكّم Google Cloud. إذا كنت بحاجة إلى حذف الدوالّ في مرحلة التطوير أو مرحلة الإنتاج، استخدِم واجهة برمجة التطبيقات Firebase.

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

الخطوات التالية

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

للاطّلاع على مزيد من المعلومات عن Cloud Functions، يمكنك أيضًا إجراء ما يلي: