الترقية من واجهة برمجة التطبيقات التي تتضمّن مساحة الاسم إلى واجهة برمجة التطبيقات modular API

على التطبيقات التي تستخدم حاليًا أي واجهة برمجة تطبيقات على Firebase Web API من مكتبات compat وحتى الإصدار 8 أو الإصدارات الأقدم منه، الانتقال إلى واجهة برمجة التطبيقات modular API من خلال اتّباع التعليمات الواردة في هذا الدليل.

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

يوصى بشدة باستخدام أداة حزم وحدات في بيئة التطوير الخاصة بك. في حال عدم استخدام واجهة برمجة التطبيقات، لن تتمكن من الاستفادة من المزايا الرئيسية لواجهة برمجة التطبيقات النمطية في تقليل حجم التطبيق. ستحتاج إلى npm أو yarn لتثبيت حزمة SDK.

ستعتمد خطوات الترقية الواردة في هذا الدليل على تطبيق ويب وهمي يستخدم حزمتَي تطوير البرامج (SDK) للمصادقة وCloud Firestore. من خلال الاطّلاع على الأمثلة، يمكنك إتقان المفاهيم والخطوات العملية المطلوبة لترقية جميع حِزم تطوير البرامج (SDK) المتوافقة مع "الويب" من Firebase.

لمحة عن مكتبات مساحات الاسم (compat)

يتوفّر نوعان من المكتبات لحزمة تطوير البرامج (SDK) على الويب لمنصة Firebase:

  • Modular - سطح جديد لواجهة برمجة تطبيقات تم تصميمه لتسهيل اهتزاز الأشجار (إزالة الرموز غير المستخدمة) لجعل تطبيق الويب صغيرًا وسريعًا قدر الإمكان.
  • Namespaced (compat): مساحة عرض مألوفة لواجهة برمجة التطبيقات ومتوافقة تمامًا مع الإصدارات السابقة من حزمة SDK، ما يتيح لك الترقية بدون تغيير كل رموز Firebase دفعة واحدة. المكتبات المنافسة لها مزايا قليلة أو معدومة في الحجم أو الأداء مقارنة بنظيرتها ذات مساحة الاسم.

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

بالنسبة إلى التطبيقات التي تستخدم حزمة SDK على الويب لمنصة Firebase على سبيل المثال، تطبيقٌ ينفِّذ استدعاء بسيط فقط إلى واجهات برمجة التطبيقات للمصادقة، قد يكون من المفيد إعادة ضبط الإعدادات القديمة التي تم تحديد مساحة اسم لها بدون استخدام المكتبات المتوافقة. في حال ترقية تطبيق من هذا النوع، يمكنك اتّباع التعليمات الواردة في هذا الدليل حول "واجهة برمجة التطبيقات modular API" بدون استخدام مكتبات التوافق.

لمحة عن عملية الترقية

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

  1. أضِف المكتبات الوحداتية ومكتبات التوافق إلى تطبيقك.
  2. حدّث عبارات الاستيراد في التعليمات البرمجية الخاصة بك للتوافق.
  3. أعِد ضبط رمز المنتج لمنتج واحد (على سبيل المثال، Authentication) على النمط النمطي.
  4. اختياري: عند هذه النقطة، عليك إزالة مكتبة التوافق مع المصادقة والرمز المتوافق مع المصادقة للتحقق من فائدة حجم التطبيق في المصادقة قبل المتابعة.
  5. أعِد ضبط الدوال لكل منتج (على سبيل المثال، Cloud Firestore وFCM وما إلى ذلك) بأسلوب الوحدات والتجميع والاختبار حتى تكتمل جميع الجوانب.
  6. عدِّل رمز الإعداد إلى النمط النمطي.
  7. قم بإزالة جميع عبارات التوافق والرموز البرمجية المتوافقة من تطبيقك.

الحصول على أحدث إصدار من حزمة SDK

للبدء، احصل على المكتبات النمطية ومكتبات التوافق باستخدام npm:

npm i firebase@10.12.2

# OR

yarn add firebase@10.12.2

تعديل عمليات الاستيراد إلى متوافق

للحفاظ على عمل التعليمة البرمجية بعد تحديث تبعياتك، قم بتغيير عبارات الاستيراد الخاصة بك لاستخدام الإصدار "compat" من كل عملية استيراد. على سبيل المثال:

قبل: الإصدار 8 أو الإصدارات الأقدم

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

بعد: التوافق

// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

إعادة التنفيذ باستخدام النمط النمطي

على الرغم من أنّ واجهات برمجة التطبيقات التي تتضمّن مساحة اسم تستند إلى مساحة اسم سلسلة نقاط ونمط خدمة، يعني الأسلوب المعياري أنّه سيتم تنظيم الرمز البرمجي بشكل أساسي حول الدوال. في modular API، لا تعرِض حزمة firebase/app والحِزم الأخرى عملية تصدير شاملة تحتوي على جميع الطرق من الحزمة. بدلاً من ذلك، تقوم الحزم بتصدير الدوال الفردية.

في واجهة برمجة التطبيقات modular API، يتم تمرير الخدمات كوسيطة أولى، ثم تستخدم الدالة تفاصيل الخدمة لتنفيذ باقي الإجراءات. دعنا نفحص كيفية عمل ذلك في مثالين يعيدان ضبط طلبات البيانات إلى واجهات برمجة تطبيقات المصادقة وCloud Firestore.

مثال 1: إعادة ضبط دالة المصادقة

قبل: التوافق

الرمز المطابق متطابق مع التعليمة البرمجية ذات مساحة الاسم، لكن عمليات الاستيراد تغيرت.

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

بعد: الوحدات النمطية

تستخدم الدالة getAuth firebaseApp كمَعلمة أولى. لا تكون الدالة onAuthStateChanged متسلسلة من المثيل auth كما لو كانت في واجهة برمجة التطبيقات التي تتضمّن مساحة الاسم، بل هي دالة مجانية تأخذ auth كمَعلمة أولى.

import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
  // Check for user status
});

تعديل التعامل مع طريقة المصادقة getRedirectResult

تؤدي واجهة برمجة التطبيقات النموذجية إلى إحداث تغيير قد يؤدي إلى عطل في getRedirectResult. في حال عدم استدعاء أي عملية إعادة توجيه، تعرض واجهة برمجة التطبيقات النمطية null بدلاً من واجهة برمجة التطبيقات ذات مساحة الاسم، والتي عرضت UserCredential مع مستخدم null.

قبل: التوافق

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

بعد: الوحدات النمطية

const result = await getRedirectResult(auth);
// Provider of the access token could be Facebook, Github, etc.
if (result === null || provider.credentialFromResult(result) === null) {
  return null;
}
return result;

المثال 2: إعادة ضبط بنية دالة Cloud Firestore

قبل: التوافق

import "firebase/compat/firestore"

const db = firebase.firestore();
db.collection("cities").where("capital", "==", true)
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

بعد: الوحدات النمطية

تستخدم الدالة getFirestore firebaseApp كمعلمة أولى، والتي تم عرضها من initializeApp في مثال سابق. يُرجى العِلم أنّ رمز إنشاء طلب البحث يختلف اختلافًا كبيرًا في واجهة برمجة التطبيقات النموذجية، إذ ليس هناك تسلسل، وقد أصبحت بعض الطرق، مثل query أو where، ظاهرة كدوال حرة.

import { getFirestore, collection, query, where, getDocs } from "firebase/firestore";

const db = getFirestore(firebaseApp);

const q = query(collection(db, "cities"), where("capital", "==", true));

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

تحديث المراجع إلى Firestore DocumentSnapshot.exists

تقدّم modular API تغييرًا قد يؤدي إلى تغيير السمة firestore.DocumentSnapshot.exists إلى طريقة. الوظيفة هي نفسها في الأساس (اختبار ما إذا كان هناك مستند) ولكن يجب إعادة ضبط التعليمة البرمجية لاستخدام الطريقة الأحدث كما هو موضح:

قبل:compat

if (snapshot.exists) {
  console.log("the document exists");
}

بعد: الوحدات النمطية

if (snapshot.exists()) {
  console.log("the document exists");
}

المثال 3: الجمع بين أنماط الرموز البرمجية ذات مساحات الاسم ونمط الرموز النمطية

يتيح لك استخدام مكتبات التوافق أثناء الترقية مواصلة استخدام الرمز البرمجي المُدرج ضمن مساحة الاسم، إلى جانب الرمز المُعاد هيكلته من أجل واجهة برمجة التطبيقات modular API. هذا يعني أنّه بإمكانك الاحتفاظ بالرمز البرمجي الحالي الذي يتضمّن مساحة الاسم لـ Cloud Firestore أثناء إعادة ضبط المصادقة أو رمز Firebase آخر في النمط النمطي، ومواصلة تجميع تطبيقك بنجاح باستخدام كلا نمطي الرموز البرمجية. وينطبق الأمر نفسه على رمز واجهة برمجة التطبيقات المقسّمة ضمن مساحة الاسم داخل منتج مثل Cloud Firestore، إذ يمكن أن تتداخل أنماط الرموز الجديدة والقديمة، طالما أنّك تستورد حزم التوافق:

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'

const docRef = firebase.firestore().doc();
getDoc(docRef);

ضع في اعتبارك أنه على الرغم من أنه سيتم تجميع تطبيقك، فلن تحصل على مزايا حجم التطبيق من التعليمات البرمجية النمطية حتى تزيل عبارات التوافق والتعليمات البرمجية بالكامل من تطبيقك.

تعديل رمز الإعداد

عدِّل رمز إعداد تطبيقك لاستخدام بنية الوحدات. من المهم تعديل هذا الرمز بعد إكمال إعادة ضبط كل الرموز البرمجية في تطبيقك، وذلك لأنّ firebase.initializeApp() يهيئ الحالة العمومية لكل من واجهات برمجة التطبيقات المتوافقة وواجهات برمجة التطبيقات، في حين تعمل الدالة initializeApp() المعيارية على إعداد الحالة النمطية فقط.

قبل: التوافق

import firebase from "firebase/compat/app"

firebase.initializeApp({ /* config */ });

بعد: الوحدات النمطية

import { initializeApp } from "firebase/app"

const firebaseApp = initializeApp({ /* config */ });

إزالة رمز التوافق

للاستفادة من مزايا الحجم التي توفّرها واجهة برمجة التطبيقات modular API، يجب في النهاية تحويل جميع عمليات الاستدعاء إلى نمط الوحدات الموضّحة أعلاه وإزالة جميع عبارات import "firebase/compat/* من الرمز. وعند الانتهاء، يجب ألا يكون هناك المزيد من الإشارات إلى مساحة الاسم العامة firebase.* أو أي رمز آخر في نمط واجهة برمجة التطبيقات الذي يتضمّن مساحة الاسم.

استخدام مكتبة التوافق من النافذة

تم تحسين واجهة برمجة التطبيقات modular API لتتوافق مع الوحدات بدلاً من استخدام كائن window في المتصفّح. كانت الإصدارات السابقة من المكتبة تتيح تحميل Firebase وإدارته باستخدام مساحة الاسم window.firebase. لا يُنصح بذلك من الآن فصاعدًا لأنه لا يسمح بإزالة الرموز غير المستخدَمة. ومع ذلك، يعمل الإصدار المتوافق من حزمة تطوير برامج JavaScript مع window للمطوّرين الذين يفضّلون عدم بدء مسار الترقية النمطي على الفور.

<script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.12.2/firebase-auth-compat.js"></script>
<script>
   const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
   const db = firebaseApp.firestore();
   const auth = firebaseApp.auth();
</script>

تستخدم مكتبة التوافق رمزًا برمجيًا نمطيًا ضمن التصميم وتزوّدها بواجهة برمجة التطبيقات نفسها التي تستخدمها واجهة برمجة التطبيقات التي تتضمّن مساحة الاسم، ويعني هذا أنّه يمكنك الرجوع إلى مرجع واجهة برمجة التطبيقات namespaced API ومقتطفات الرموز المميّزة بمساحة الاسم للحصول على التفاصيل. لا ننصح باستخدام هذه الطريقة على المدى الطويل، ولكن كبداية للترقية إلى المكتبة ذات الوحدات النمطية بالكامل.

مزايا وقيود حزمة تطوير البرامج (SDK) النموذجية

تتميّز حزمة تطوير البرامج (SDK) المؤلفة من وحدات بالكامل بهذه المزايا مقارنةً بالإصدارات السابقة:

  • وتتيح حزمة تطوير البرامج (SDK) النموذجية تقليل حجم التطبيق بشكل كبير. وهي تعتمد التنسيق الحديث لوحدة JavaScript، ما يسمح بممارسات "اهتزاز الشجرة" التي تستورد فيها العناصر التي يحتاجها تطبيقك فقط. اعتمادًا على تطبيقك، يمكن أن يؤدي اهتزاز الشجرة باستخدام حزمة تطوير البرامج (SDK) النمطية إلى تقليل حجمها بمقدار 80% عن التطبيقات المماثلة المُنشأة باستخدام واجهة برمجة التطبيقات المخصّصة لمساحة الاسم.
  • ستستمر حزمة SDK النموذجية في الاستفادة من التطوير المستمر للميزات، على عكس واجهة برمجة التطبيقات التي تتضمّن مساحة الاسم.