بالنسبة إلى التطبيقات التي تستخدم أي واجهة برمجة تطبيقات ويب من Firebase تستند إلى مساحة الاسم، بدءًا من مكتبات compat
وصولاً إلى الإصدار 8 أو الإصدارات الأقدم، ننصحك
بالانتقال إلى واجهة برمجة التطبيقات modular API باتّباع التعليمات الواردة في هذا الدليل.
يفترض هذا الدليل أنّك على دراية بواجهة namespaced API وأنّك ستستفيد من حزمة وحدات مثل webpack أو Rollup للترقية والتطوير المستمر للتطبيقات المستندة إلى وحدات.
ننصح بشدة باستخدام حزمة وحدات في بيئة التطوير. إذا لم تستخدم إحدى هذه الأدوات، لن تتمكّن من الاستفادة من المزايا الرئيسية لواجهة برمجة التطبيقات Modular API في تقليل حجم التطبيق. ستحتاج إلى npm أو yarn لتثبيت حزمة تطوير البرامج (SDK).
ستستند خطوات الترقية في هذا الدليل إلى تطبيق ويب افتراضي يستخدم حزمتَي تطوير البرامج (SDK) Authentication وCloud Firestore. من خلال العمل على الأمثلة، يمكنك إتقان المفاهيم والخطوات العملية المطلوبة لترقية جميع حزم تطوير البرامج (SDK) للويب من Firebase المتوافقة.
لمحة عن مكتبات مساحة الاسم (compat)
هناك نوعان من المكتبات المتاحة لحزمة تطوير البرامج (SDK) على الويب من Firebase:
- النموذجية: واجهة برمجة تطبيقات جديدة مصمّمة لتسهيل عملية إزالة الرموز البرمجية غير المستخدَمة لجعل تطبيق الويب صغيرًا وسريعًا قدر الإمكان
- مساحة الاسم (
compat): واجهة برمجة تطبيقات مألوفة ومتوافقة تمامًا مع الإصدارات السابقة من حزمة تطوير البرامج (SDK)، ما يتيح لك الترقية بدون تغيير كل رموز Firebase البرمجية في آنٍ واحد. لا تتمتع مكتبات التوافق بمزايا تُذكر من حيث الحجم أو الأداء مقارنةً بنظيراتها التي تستخدم مساحات الأسماء.
يفترض هذا الدليل أنّك ستستفيد من مكتبات التوافق لتسهيل عملية الترقية. تتيح لك هذه المكتبات مواصلة استخدام الرمز البرمجي الذي يتضمّن مساحة اسم إلى جانب الرمز البرمجي الذي تمت إعادة تصميمه ليتوافق مع modular API. هذا يعني أنّه يمكنك تجميع تطبيقك وتصحيح أخطائه بسهولة أكبر أثناء عملية الترقية.
بالنسبة إلى التطبيقات التي تستخدم حزمة تطوير البرامج (SDK) لمنصة Firebase على الويب بشكل محدود جدًا، مثل تطبيق يُجري طلبًا بسيطًا فقط لواجهات برمجة تطبيقات Authentication، قد يكون من العملي إعادة هيكلة الرمز البرمجي القديم الذي يستخدم مساحات الأسماء بدون استخدام مكتبات التوافق. إذا كنت بصدد ترقية تطبيق من هذا النوع، يمكنك اتّباع التعليمات الواردة في هذا الدليل بشأن "modular API" بدون استخدام مكتبات التوافق.
لمحة عن عملية الترقية
يتم تحديد نطاق كل خطوة من خطوات عملية الترقية حتى تتمكن من الانتهاء من تحرير المصدر لتطبيقك ثم تجميعه وتشغيله دون أي عطل. باختصار، إليك ما ستفعله لترقية تطبيق:
- أضِف المكتبات المعيارية ومكتبات التوافق إلى تطبيقك.
- عدِّل عبارات الاستيراد في الرمز البرمجي إلى compat.
- أعِد هيكلة الرمز لمنتج واحد (مثلاً، Authentication) إلى النمط المعياري.
- اختياري: في هذه المرحلة، يمكنك إزالة مكتبة التوافق Authentication ورمز التوافق لـ Authentication من أجل الاستفادة من حجم التطبيق لـ Authentication قبل المتابعة.
- أعِد صياغة الدوال لكل منتج (على سبيل المثال، Cloud Firestore وFCM وما إلى ذلك) إلى النمط المعياري، مع تجميعها واختبارها حتى تكتمل جميع المجالات.
- عدِّل رمز الإعداد إلى النمط المعياري.
- أزِل جميع عبارات ورموز التوافق المتبقية من تطبيقك.
الحصول على أحدث إصدار من حزمة SDK
للبدء، احصل على المكتبات المعيارية ومكتبات التوافق باستخدام npm:
npm i firebase@13.2.0 # OR yarn add firebase@13.2.0
تعديل عمليات الاستيراد لتصبح متوافقة
للحفاظ على عمل الرمز البرمجي بعد تحديث التبعيات، يجب تغيير عبارات الاستيراد لاستخدام إصدار "compat" لكل عملية استيراد. على سبيل المثال:
قبل: الإصدار 8 أو الإصدارات الأقدم
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
بعد: compat
// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
إعادة تصميم الرمز البرمجي ليتوافق مع النمط المعياري
تستند واجهات برمجة التطبيقات namespaced API إلى نمط الخدمة ومساحة الاسم المتسلسلة بنقاط، بينما يعني النهج المستند إلى الوحدات أنّ الرمز البرمجي سيتم تنظيمه بشكل أساسي حول الدوال. في واجهة برمجة التطبيقات هذه، لا تعرض حزمة firebase/app والحزم الأخرى عملية تصدير شاملة تحتوي على جميع الطرق من الحزمة. بدلاً من ذلك، تصدّر الحزم دوال فردية.
في واجهة برمجة التطبيقات modular API، يتم تمرير الخدمات كوسيطة أولى، ثم تستخدم الدالة تفاصيل الخدمة لتنفيذ بقية المهام. لنلقِ نظرة على كيفية عمل ذلك من خلال مثالَين يعيدان هيكلة الطلبات إلى واجهتَي برمجة التطبيقات Authentication وCloud Firestore.
المثال 1: إعادة تصميم دالة Authentication
قبل: compat
رمز التوافق مطابق للرمز الذي يتضمّن مساحة الاسم، ولكن تم تغيير عمليات الاستيراد.
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 كما هو الحال
في namespaced API، بل هي دالة
مستقلة تأخذ auth كمَعلمة أولى.
import { getAuth, onAuthStateChanged } from "firebase/auth";
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
// Check for user status
});
تعديل طريقة معالجة طريقة المصادقة getRedirectResult
تُقدّم واجهة برمجة التطبيقات هذه تغييرًا قد يؤدي إلى عطل في getRedirectResult. عندما لا يتم استدعاء أي عملية إعادة توجيه، تعرض واجهة برمجة التطبيقات modular API القيمة null على عكس واجهة برمجة التطبيقات namespaced API التي تعرض القيمة UserCredential مع مستخدم null.
قبل: compat
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
قبل: compat
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 في مثال سابق. يُرجى ملاحظة أنّ الرمز البرمجي لإنشاء طلب بحث يختلف كثيرًا في modular API؛ إذ لا يوجد تسلسل، كما أنّ الطرق مثل 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 إلى طريقة. تتشابه الوظيفتان بشكل أساسي (اختبار ما إذا كان المستند موجودًا)، ولكن عليك إعادة تصميم الرمز البرمجي لاستخدام الطريقة الأحدث كما هو موضّح:
Before:compat
if (snapshot.exists) {
console.log("the document exists");
}
بعد: شرائح مفصّلة
if (snapshot.exists()) {
console.log("the document exists");
}
المثال 3: الجمع بين أنماط الرموز البرمجية ذات مساحة الاسم والوحدات
يتيح لك استخدام مكتبات التوافق أثناء الترقية مواصلة استخدام الرموز البرمجية التي تستخدم مساحات الأسماء إلى جانب الرموز البرمجية التي تمت إعادة تصميمها لتتوافق مع modular API. هذا يعني أنّه يمكنك الاحتفاظ بالرمز الحالي المستند إلى مساحة الاسم لـ Cloud Firestore أثناء إعادة تصميم Authentication أو رمز Firebase SDK آخر إلى النمط المعياري، وسيظل بإمكانك تجميع تطبيقك بنجاح باستخدام كلا نمطَي الرمز. ينطبق الأمر نفسه على الرموز البرمجية لواجهات برمجة التطبيقات التي تستخدم مساحات الأسماء والوحدات داخل منتج مثل 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() الوحدات الحالة للوحدات فقط.
قبل: compat
import firebase from "firebase/compat/app"
firebase.initializeApp({ /* config */ });
بعد: شرائح مفصّلة
import { initializeApp } from "firebase/app"
const firebaseApp = initializeApp({ /* config */ });
إزالة رمز التوافق
للاستفادة من حجم واجهة برمجة التطبيقات المعيارية، عليك في النهاية
تحويل جميع الاستدعاءات إلى النمط المعياري الموضّح أعلاه وإزالة جميع
عبارات import "firebase/compat/* من الرمز البرمجي. عند الانتهاء، من المفترض ألا تكون هناك أي إشارات أخرى إلى مساحة الاسم العامة firebase.* أو أي رمز آخر في نمط namespaced API.
استخدام مكتبة التوافق من النافذة
تم تحسين واجهة برمجة التطبيقات هذه للعمل مع الوحدات بدلاً من عنصر window في المتصفّح. كانت الإصدارات السابقة من المكتبة تسمح بتحميل Firebase وإدارته باستخدام مساحة الاسم window.firebase. لا ننصح باتّباع هذا النهج من الآن فصاعدًا لأنّه لا يسمح بإزالة الرموز البرمجية غير المستخدَمة.
ومع ذلك، فإنّ إصدار التوافق من حزمة JavaScript SDK يعمل مع window
للمطوّرين الذين يفضّلون عدم البدء فورًا في مسار الترقية إلى الإصدار الموحّد.
<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-auth-compat.js"></script>
<script>
const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
const db = firebaseApp.firestore();
const auth = firebaseApp.auth();
</script>
تستخدم مكتبة التوافق رمزًا برمجيًا معياريًا في الخلفية وتوفّره مع واجهة برمجة التطبيقات نفسها مثل namespaced API، ما يعني أنّه يمكنك الرجوع إلى مرجع namespaced API ومقتطفات الرموز البرمجية الخاصة بـ namespaced API للحصول على التفاصيل. لا يُنصح باستخدام هذه الطريقة على المدى الطويل، ولكن كبداية للترقية إلى المكتبة المعيارية بالكامل.
مزايا حزمة SDK النموذجية والقيود المفروضة عليها
تتميّز حزمة تطوير البرامج (SDK) التي تم تقسيمها بالكامل إلى وحدات بالمزايا التالية مقارنةً بالإصدارات السابقة:
- تتيح حزمة SDK هذه تقليل حجم التطبيق بشكل كبير. ويعتمد على تنسيق وحدة JavaScript الحديث، ما يسمح بممارسات "إزالة الرموز غير المستخدَمة" التي تستورد فيها فقط العناصر التي يحتاجها تطبيقك. بناءً على تطبيقك، يمكن أن يؤدي استخدام تقنية tree-shaking مع حزمة SDK المستندة إلى الوحدات إلى تقليل عدد الكيلوبايت بنسبة %80 مقارنةً بتطبيق مماثل تم إنشاؤه باستخدام namespaced API.
- ستستمر حزمة تطوير البرامج (SDK) المعيارية في الاستفادة من تطوير الميزات المستمر، بينما لن تستفيد واجهة برمجة التطبيقات ذات مساحة الاسم.