1. قبل البدء
حزمة Firebase JS SDK النموذجية هي إعادة كتابة لحزمة JS SDK الحالية وسيتم إطلاقها كالإصدار الرئيسي التالي. تتيح هذه الميزة للمطوّرين استبعاد الرموز غير المستخدَمة من حزمة تطوير البرامج (SDK) في Firebase JS لإنشاء حِزم أصغر وتحقيق أداء أفضل.
الفرق الأكثر وضوحًا في حزمة تطوير البرامج (SDK) المستندة إلى وحدات JS هو أنّ الميزات أصبحت منظَّمة في دوال عائمة حرة يمكنك استيرادها، بدلاً من مساحة اسم firebase واحدة تتضمّن كل شيء. تتيح طريقة تنظيم الرموز البرمجية الجديدة هذه إمكانية إزالة الأجزاء غير المستخدَمة من الرموز البرمجية، وسنتعرّف على كيفية ترقية أي تطبيق يستخدم حاليًا حزمة تطوير البرامج (SDK) لإصدار JavaScript 8 من Firebase إلى الحزمة الجديدة المستندة إلى الوحدات.
لتوفير عملية ترقية سلسة، يتم توفير مجموعة من حِزم التوافق. في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية استخدام حِزم التوافق لنقل التطبيق جزءًا جزءًا.
ما ستنشئه
في هذا الدرس العملي، ستنقل تدريجيًا تطبيقًا حاليًا على الويب لقائمة مراقبة الأسهم يستخدم حزمة تطوير البرامج (SDK) لإصدار JavaScript 8 إلى حزمة تطوير البرامج (SDK) الجديدة لإصدار JavaScript المجزّأ على ثلاث مراحل:
- ترقية التطبيق لاستخدام حِزم التوافق
- ترقية التطبيق من حِزم التوافق إلى واجهة برمجة التطبيقات النموذجية جزءًا تلو الآخر
- استخدام Firestore Lite، وهو إصدار خفيف من حزمة تطوير البرامج (SDK) لخدمة Firestore، لتحسين أداء التطبيق بشكل أكبر

يركّز هذا الدرس العملي على ترقية حزمة تطوير البرامج (SDK) لنظام Firebase. يتم تجاهل المفاهيم الأخرى ومجموعات الرموز البرمجية، ويتم توفيرها لك لنسخها ولصقها ببساطة.
المتطلبات
2. بدء الإعداد
الحصول على الرمز
كل ما تحتاج إليه لهذا المشروع موجود في مستودع Git. للبدء، عليك الحصول على الرمز وفتحه في بيئة التطوير المفضّلة لديك.
استنسِخ مستودع Github الخاص بالدرس العملي من سطر الأوامر:
git clone https://github.com/FirebaseExtended/codelab-modular-sdk.git
بدلاً من ذلك، إذا لم يكن git مثبّتًا لديك، يمكنك تنزيل المستودع كملف ZIP وفك ضغط ملف ZIP الذي تم تنزيله.
استيراد التطبيق
- باستخدام بيئة التطوير المتكاملة (IDE)، افتح الدليل
codelab-modular-sdkأو استورِده. - نفِّذ الأمر
npm installلتثبيت التبعيات المطلوبة لإنشاء التطبيق وتشغيله محليًا. - نفِّذ
npm run buildلإنشاء التطبيق. - نفِّذ الأمر
npm run serveلبدء تشغيل خادم الويب - افتح علامة تبويب متصفّح على http://localhost:8080

3- تحديد مقياس أساسي
ما هي نقطة البداية؟
نقطة البداية هي تطبيق قائمة مراقبة الأسهم المصمَّم خصيصًا لهذا الدرس البرمجي. تم تبسيط الرمز البرمجي لتوضيح المفاهيم الواردة في هذا الدرس العملي، كما أنّه لا يتضمّن سوى القليل من معالجة الأخطاء. إذا اخترت إعادة استخدام أيّ من هذا الرمز في تطبيق متاح للجميع، تأكَّد من معالجة أي أخطاء واختبار جميع الرموز بالكامل.
تأكَّد من أنّ كل شيء يعمل في التطبيق:
- سجِّل الدخول بشكل مجهول الهوية باستخدام زر تسجيل الدخول في أعلى يسار الصفحة.
- بعد تسجيل الدخول، ابحث عن "NFLX" و"SBUX" و "T" وأضِفها إلى قائمة المراقبة من خلال النقر على الزر إضافة وكتابة الأحرف والنقر على صف نتيجة البحث الذي يظهر أدناه.
- أزِل سهمًا من قائمة المراقبة بالنقر على x في نهاية الصف.
- شاهِد آخر المعلومات حول سعر السهم في الوقت الفعلي.
- افتح "أدوات مطوّري البرامج في Chrome"، وانتقِل إلى علامة التبويب الشبكة، ثم ضَع علامة في المربّعين إيقاف ذاكرة التخزين المؤقت واستخدام صفوف طلب كبيرة. يضمن خيار إيقاف ذاكرة التخزين المؤقت أن نحصل دائمًا على آخر التغييرات بعد إعادة التحميل، بينما يتيح خيار استخدام صفوف طلب كبيرة للصف عرض كلّ من حجم البيانات المرسَلة وحجم المورد. في هذا الدرس التطبيقي حول الترميز، يهمّنا بشكل أساسي حجم
main.js.

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

يمكنك الآن البدء في نقل التطبيق إلى واجهة برمجة التطبيقات الجديدة ذات الوحدات.
4. استخدام حِزم التوافق
تتيح لك حِزم التوافق الترقية إلى إصدار حزمة SDK الجديد بدون تغيير كل رمز Firebase في وقت واحد. يمكنك ترقيتها إلى واجهة برمجة التطبيقات المعيارية تدريجيًا.
في هذه الخطوة، ستتم ترقية مكتبة Firebase من الإصدار 8 إلى الإصدار الجديد وتغيير الرمز البرمجي لاستخدام حِزم التوافق. في الخطوات التالية، ستتعرّف على كيفية ترقية رمز Firebase Auth فقط لاستخدام واجهة برمجة التطبيقات النموذجية أولاً، ثم ترقية رمز Firestore.
في نهاية كل خطوة، يجب أن تتمكّن من تجميع التطبيق وتشغيله بدون حدوث أي أعطال، وأن تلاحظ انخفاضًا في حجم الحِزمة أثناء نقل كل منتج.
الحصول على حزمة تطوير البرامج (SDK) الجديدة
ابحث عن قسم العناصر التابعة في package.json واستبدِله بما يلي:
package.json
"dependencies": {
"firebase": "^9.0.0"
}
إعادة تثبيت التبعيات
بما أنّنا غيّرنا إصدار التبعية، علينا إعادة تنفيذ npm install للحصول على الإصدار الجديد من التبعية.
تغيير مسارات الاستيراد
يتم عرض حِزم التوافق ضمن الوحدة الفرعية firebase/compat، لذا سنعدّل مسارات الاستيراد وفقًا لذلك:
- الانتقال إلى الملف
src/firebase.ts - استبدِل عمليات الاستيراد الحالية بعمليات الاستيراد التالية:
src/firebase.ts
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
التأكّد من أنّ التطبيق يعمل
- نفِّذ
npm run buildلإعادة إنشاء التطبيق. - افتح علامة تبويب متصفّح وانتقِل إلى http://localhost:8080 أو أعِد تحميل علامة التبويب الحالية.
- العب باستخدام التطبيق، ومن المفترض أن يظل كل شيء يعمل.
5- ترقية Auth لاستخدام واجهة برمجة التطبيقات النموذجية
يمكنك ترقية منتجات Firebase بأي ترتيب. في هذا الدرس العملي، ستتم ترقية Auth أولاً للتعرّف على المفاهيم الأساسية لأنّ واجهة برمجة التطبيقات Auth بسيطة نسبيًا. تتطلّب ترقية Firestore بعض الخطوات الإضافية، وسنتعرّف على كيفية تنفيذها في الفقرة التالية.
تعديل عملية تهيئة المصادقة
- الانتقال إلى الملف
src/firebase.ts - أضِف عملية الاستيراد التالية:
src/firebase.ts
import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
- حذف
import ‘firebase/compat/auth'. - استبدال
export const firebaseAuth = app.auth();بما يلي:
src/firebase.ts
export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
- أزِل
export type User = firebase.User;في نهاية الملف. سيتم تصديرUserمباشرةً فيsrc/auth.tsالذي ستغيّره بعد ذلك.
تعديل رمز المصادقة
- الانتقال إلى الملف
src/auth.ts - أضِف عمليات الاستيراد التالية إلى أعلى الملف:
src/auth.ts
import {
signInAnonymously,
signOut,
onAuthStateChanged,
User
} from 'firebase/auth';
- إزالة
Userمنimport { firebaseAuth, User } from './firebase';لأنّك استوردتUserمن‘firebase/auth'. - تعديل الدوال لاستخدام واجهة برمجة التطبيقات النموذجية
كما رأيت سابقًا عند تعديل عبارة الاستيراد، يتم تنظيم الحِزم في الإصدار 9 حول الدوال التي يمكنك استيرادها، وذلك على عكس واجهات برمجة التطبيقات في الإصدار 8 التي تستند إلى نمط مساحة الاسم والخدمة المرتبطين بنقطة. هذه الطريقة الجديدة لتنظيم الرموز البرمجية هي التي تتيح إزالة الرموز البرمجية غير المستخدَمة، لأنّها تسمح لأدوات الإنشاء بتحليل الرموز البرمجية المستخدَمة وغير المستخدَمة.
في الإصدار 9، يتم تمرير الخدمات كمعلَمة أولى إلى الدوال. الخدمات هي العناصر التي تحصل عليها من تهيئة إحدى خدمات Firebase، مثل العنصر الذي يتم عرضه من getAuth() أو initializeAuth(). تحتفظ هذه الكائنات بحالة خدمة Firebase معيّنة، وتستخدِم الدالة الحالة لتنفيذ مهامها. لنطبّق هذا النمط لتنفيذ الوظائف التالية:
src/auth.ts
export function firebaseSignInAnonymously() {
return signInAnonymously(firebaseAuth);
}
export function firebaseSignOut() {
return signOut(firebaseAuth);
}
export function onUserChange(callback: (user: User | null) => void) {
return onAuthStateChanged(firebaseAuth, callback);
}
export { User } from 'firebase/auth';
التأكّد من أنّ التطبيق يعمل
- نفِّذ
npm run buildلإعادة إنشاء التطبيق. - افتح علامة تبويب متصفّح على http://localhost:8080 أو أعِد تحميل علامة التبويب الحالية
- العب باستخدام التطبيق، ومن المفترض أن يظل كل شيء يعمل.
التحقّق من حجم الحزمة
- افتح "أدوات مطوّري البرامج في Chrome".
- انتقِل إلى علامة التبويب الشبكة.
- أعِد تحميل الصفحة لالتقاط طلبات الشبكة.
- ابحث عن ملف main.js وتحقّق من حجمه. لقد قلّلت حجم الحزمة بمقدار 100 كيلوبايت (36 كيلوبايت مضغوطة بتنسيق gzip)، أو أصغر بنسبة% 22 تقريبًا من خلال تغيير بضعة أسطر فقط من الرمز. يتم أيضًا تحميل الموقع الإلكتروني بشكل أسرع بمقدار 0.75 ثانية عند الاتصال بشبكة الجيل الثالث البطيئة.

6. ترقية تطبيق Firebase وFirestore لاستخدام واجهة برمجة التطبيقات النموذجية
تعديل عملية إعداد Firebase
- الانتقال إلى الملف
src/firebase.ts. - استبدال
import firebase from ‘firebase/compat/app';بما يلي:
src/firebase.ts
import { initializeApp } from 'firebase/app';
- استبدال
const app = firebase.initializeApp({...});بما يلي:
src/firebase.ts
const app = initializeApp({
apiKey: "AIzaSyBnRKitQGBX0u8k4COtDTILYxCJuMf7xzE",
authDomain: "exchange-rates-adcf6.firebaseapp.com",
databaseURL: "https://exchange-rates-adcf6.firebaseio.com",
projectId: "exchange-rates-adcf6",
storageBucket: "exchange-rates-adcf6.firebasestorage.app",
messagingSenderId: "875614679042",
appId: "1:875614679042:web:5813c3e70a33e91ba0371b"
});
تعديل عملية إعداد Firestore
- في الملف نفسه، استبدِل
src/firebase.ts,بـimport 'firebase/compat/firestore';
src/firebase.ts
import { getFirestore } from 'firebase/firestore';
- استبدال
export const firestore = app.firestore();بما يلي:
src/firebase.ts
export const firestore = getFirestore();
- إزالة جميع الأسطر بعد "
export const firestore = ..."
تعديل عمليات الاستيراد
- فتح الملف
src/services.ts. - إزالة
FirestoreFieldPathوFirestoreFieldValueوQuerySnapshotمن عملية الاستيراد من المفترض أن يبدو الاستيراد من'./firebase'الآن على النحو التالي:
src/services.ts
import { firestore } from './firebase';
- استورِد الدوال والأنواع التي ستستخدمها في أعلى الملف:
**src/services.ts**
import {
collection,
getDocs,
doc,
setDoc,
arrayUnion,
arrayRemove,
onSnapshot,
query,
where,
documentId,
QuerySnapshot
} from 'firebase/firestore';
تعديل search()
- أنشِئ مرجعًا للمجموعة التي تحتوي على جميع رموز الأسهم:
src/services.ts
const tickersCollRef = collection(firestore, 'current');
- استخدِم
getDocs()لجلب جميع المستندات من المجموعة:
src/services.ts
const tickers = await getDocs(tickersCollRef);
يمكنك الاطّلاع على search() للحصول على الرمز النهائي.
تعديل الدالة addToWatchList()
استخدِم doc() لإنشاء مرجع مستند إلى قائمة المراقبة الخاصة بالمستخدم، ثم أضِف رمزًا إلى هذا المرجع باستخدام setDoc() مع arrayUnion():
src/services.ts
export function addToWatchList(ticker: string, user: User) {
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
return setDoc(watchlistRef, {
tickers: arrayUnion(ticker)
}, { merge: true });
}
تعديل deleteFromWatchList()
وبالمثل، يمكنك إزالة رمز سهم من قائمة مشاهدة المستخدم باستخدام setDoc() مع arrayRemove():
src/services.ts
export function deleteFromWatchList(ticker: string, user: User) {
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
return setDoc(watchlistRef, {
tickers: arrayRemove(ticker)
}, { merge: true });
}
تعديل subscribeToTickerChanges()
- استخدِم
doc()لإنشاء مرجع مستند إلى قائمة المراقبة الخاصة بالمستخدم أولاً، ثم استمِع إلى تغييرات قائمة المراقبة باستخدامonSnapshot():
src/services.ts
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
/* subscribe to ticker price changes */
});
- بعد إضافة رموز الأسهم إلى قائمة المراقبة، استخدِم
query()لإنشاء طلب بحث لجلب أسعارها، واستخدِمonSnapshot()للاستماع إلى تغييرات أسعارها:
src/services.ts
const priceQuery = query(
collection(firestore, 'current'),
where(documentId(), 'in', tickers)
);
unsubscribePrevTickerChanges = onSnapshot(priceQuery, snapshot => {
if (firstload) {
performance && performance.measure("initial-data-load");
firstload = false;
logPerformance();
}
const stocks = formatSDKStocks(snapshot);
callback(stocks);
});
راجِع subscribeToTickerChanges() للاطّلاع على عملية التنفيذ الكاملة.
تعديل subscribeToAllTickerChanges()
أولاً، ستستخدم collection() لإنشاء مرجع إلى المجموعة التي تحتوي على أسعار جميع رموز الأسهم، ثم ستستخدم onSnapshot() للاستماع إلى تغييرات الأسعار:
src/services.ts
export function subscribeToAllTickerChanges(callback: TickerChangesCallBack) {
const tickersCollRef = collection(firestore, 'current');
return onSnapshot(tickersCollRef, snapshot => {
if (firstload) {
performance && performance.measure("initial-data-load");
firstload = false;
logPerformance();
}
const stocks = formatSDKStocks(snapshot);
callback(stocks);
});
}
التأكّد من أنّ التطبيق يعمل
- نفِّذ
npm run buildلإعادة إنشاء التطبيق. - افتح علامة تبويب متصفّح على http://localhost:8080 أو أعِد تحميل علامة التبويب الحالية
- العب باستخدام التطبيق، ومن المفترض أن يظل كل شيء يعمل.
التحقّق من حجم الحزمة
- افتح "أدوات مطوّري البرامج في Chrome".
- انتقِل إلى علامة التبويب الشبكة.
- أعِد تحميل الصفحة لالتقاط طلبات الشبكة.
- ابحث عن
main.jsوتحقّق من حجمه. قارِن حجم الحزمة الجديد بحجم الحزمة الأصلي مرة أخرى، لقد قلّلنا حجم الحزمة بأكثر من 200 كيلوبايت (63.8 كيلوبايت مضغوط بتنسيق gzip)، أو أصغر بنسبة% 50، ما يعني أنّ وقت التحميل أسرع بمقدار 1.3 ثانية.

7. استخدام Firestore Lite لتسريع عملية العرض الأوّلي للصفحة
ما هي Firestore Lite؟
توفّر حزمة تطوير البرامج (SDK) الخاصة بخدمة Firestore التخزين المؤقت المعقّد، والبث في الوقت الفعلي، والتخزين الدائم، والمزامنة بلا إنترنت في علامات تبويب متعددة، وعمليات إعادة المحاولة، والتزامن المتفائل، وغير ذلك الكثير، وبالتالي فإنّ حجمها كبير جدًا. ولكن قد تحتاج ببساطة إلى الحصول على البيانات مرة واحدة، بدون الحاجة إلى أي من الميزات المتقدّمة. في هذه الحالات، أنشأت Firestore حلاً بسيطًا وخفيفًا، وهو حزمة جديدة تمامًا باسم Firestore Lite.
من حالات الاستخدام الرائعة لـ Firestore Lite تحسين أداء عرض الصفحة الأولي، حيث تحتاج فقط إلى معرفة ما إذا كان المستخدم قد سجّل الدخول أم لا، ثم قراءة بعض البيانات من Firestore لعرضها.
في هذه الخطوة، ستتعرّف على كيفية استخدام Firestore lite لتقليل حجم الحِزمة من أجل تسريع عرض الصفحة الأوّلية، ثم تحميل حزمة تطوير البرامج (SDK) الرئيسية لخدمة Firestore بشكل ديناميكي للاشتراك في التحديثات في الوقت الفعلي.
ستعيد تصميم الرمز البرمجي ليصبح على النحو التالي:
- نقل الخدمات التي تعمل في الوقت الفعلي إلى ملف منفصل، حتى يمكن تحميلها بشكل ديناميكي باستخدام ميزة "الاستيراد الديناميكي"
- أنشئ دوال جديدة لاستخدام Firestore Lite من أجل استرداد قائمة المراقبة وأسعار الأسهم.
- استخدِم دوال Firestore Lite الجديدة لاسترداد البيانات من أجل عرض الصفحة الأولي، ثم حمِّل الخدمات في الوقت الفعلي بشكل ديناميكي للاستماع إلى التحديثات في الوقت الفعلي.
نقل الخدمات في الوقت الفعلي إلى ملف جديد
- أنشئ ملفًا جديدًا باسم
src/services.realtime.ts. - انقل الدالتَين
subscribeToTickerChanges()وsubscribeToAllTickerChanges()منsrc/services.tsإلى الملف الجديد. - أضِف عمليات الاستيراد اللازمة إلى أعلى الملف الجديد.
لا يزال عليك إجراء بعض التغييرات هنا:
- أولاً، أنشئ مثيلاً من Firestore من حزمة تطوير البرامج الرئيسية لمنصة Firestore في أعلى الملف الذي سيتم استخدامه في الدوال. لا يمكنك استيراد مثيل Firestore من
firebase.tsهنا لأنّك ستغيّره إلى مثيل Firestore Lite في بضع خطوات، وسيتم استخدامه فقط لعرض الصفحة الأولي. - ثانيًا، تخلَّص من المتغيّر
firstloadوكتلة if المحمية به. سيتم نقل وظائفها إلى دوال جديدة ستنشئها في الخطوة التالية.
src/services.realtime.ts
import { User } from './auth'
import { TickerChange } from './models';
import { collection, doc, onSnapshot, query, where, documentId, getFirestore } from 'firebase/firestore';
import { formatSDKStocks } from './services';
const firestore = getFirestore();
type TickerChangesCallBack = (changes: TickerChange[]) => void
export function subscribeToTickerChanges(user: User, callback: TickerChangesCallBack) {
let unsubscribePrevTickerChanges: () => void;
// Subscribe to watchlist changes. We will get an update whenever a ticker is added/deleted to the watchlist
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
const doc = snapshot.data();
const tickers = doc ? doc.tickers : [];
if (unsubscribePrevTickerChanges) {
unsubscribePrevTickerChanges();
}
if (tickers.length === 0) {
callback([]);
} else {
// Query to get current price for tickers in the watchlist
const priceQuery = query(
collection(firestore, 'current'),
where(documentId(), 'in', tickers)
);
// Subscribe to price changes for tickers in the watchlist
unsubscribePrevTickerChanges = onSnapshot(priceQuery, snapshot => {
const stocks = formatSDKStocks(snapshot);
callback(stocks);
});
}
});
return () => {
if (unsubscribePrevTickerChanges) {
unsubscribePrevTickerChanges();
}
unsubscribe();
};
}
export function subscribeToAllTickerChanges(callback: TickerChangesCallBack) {
const tickersCollRef = collection(firestore, 'current');
return onSnapshot(tickersCollRef, snapshot => {
const stocks = formatSDKStocks(snapshot);
callback(stocks);
});
}
استخدام Firestore lite لجلب البيانات
- فتح
src/services.ts. - تغيير مسار الاستيراد من
‘firebase/firestore'إلى‘firebase/firestore/lite',لإضافةgetDocوإزالةonSnapshotمن قائمة الاستيراد:
src/services.ts
import {
collection,
getDocs,
doc,
setDoc,
arrayUnion,
arrayRemove,
// onSnapshot, // firestore lite doesn't support realtime updates
query,
where,
documentId,
QuerySnapshot,
getDoc // add this import
} from 'firebase/firestore/lite';
- أضِف دوالاً لجلب البيانات اللازمة لعرض الصفحة الأوّلي باستخدام Firestore Lite:
src/services.ts
export async function getTickerChanges(tickers: string[]): Promise<TickerChange[]> {
if (tickers.length === 0) {
return [];
}
const priceQuery = query(
collection(firestore, 'current'),
where(documentId(), 'in', tickers)
);
const snapshot = await getDocs(priceQuery);
performance && performance.measure("initial-data-load");
logPerformance();
return formatSDKStocks(snapshot);
}
export async function getTickers(user: User): Promise<string[]> {
const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const data = (await getDoc(watchlistRef)).data();
return data ? data.tickers : [];
}
export async function getAllTickerChanges(): Promise<TickerChange[]> {
const tickersCollRef = collection(firestore, 'current');
const snapshot = await getDocs(tickersCollRef);
performance && performance.measure("initial-data-load");
logPerformance();
return formatSDKStocks(snapshot);
}
- افتح
src/firebase.ts، وغيِّر مسار الاستيراد من‘firebase/firestore'إلى‘firebase/firestore/lite':
src/firebase.ts
import { getFirestore } from 'firebase/firestore/lite';
ربط كل هذه العناصر معًا
- فتح
src/main.ts. - ستحتاج إلى الدوال التي تم إنشاؤها حديثًا لجلب البيانات من أجل عرض الصفحة الأولي، وإلى بعض دوال المساعدة لإدارة حالة التطبيق. لذا، عدِّل عمليات الاستيراد الآن:
src/main.ts
import { renderLoginPage, renderUserPage } from './renderer';
import { getAllTickerChanges, getTickerChanges, getTickers } from './services';
import { onUserChange } from './auth';
import { getState, setRealtimeServicesLoaded, setUser } from './state';
import './styles.scss';
- حمِّل
src/services.realtimeباستخدام عملية استيراد ديناميكية في أعلى الملف. المتغيّرloadRealtimeServiceهو وعد سيتم تنفيذه باستخدام الخدمات في الوقت الفعلي بعد تحميل الرمز. ستستخدمه لاحقًا للاشتراك في تلقّي آخر المعلومات في الوقت الفعلي.
src/main.ts
const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
setRealtimeServicesLoaded(true);
});
- غيِّر دالة معاودة الاتصال الخاصة بـ
onUserChange()إلى الدالةasync، حتى نتمكّن من استخدامawaitفي نص الدالة:
src/main.ts
onUserChange(async user => {
// callback body
});
- الآن، استرجِع البيانات لعرض الصفحة الأوّلية باستخدام الدوال الجديدة التي أنشأناها في الخطوة السابقة.
في دالة الاستدعاء onUserChange()، ابحث عن شرط if الذي يتم فيه تسجيل دخول المستخدم، ثم انسخ الرمز والصقه داخل عبارة if:
src/main.ts
onUserChange(async user => {
// LEAVE THE EXISTING CODE UNCHANGED HERE
...
if (user) {
// REPLACE THESE LINES
// user page
setUser(user);
// show loading screen in 500ms
const timeoutId = setTimeout(() => {
renderUserPage(user, {
loading: true,
tableData: []
});
}, 500);
// get data once if realtime services haven't been loaded
if (!getState().realtimeServicesLoaded) {
const tickers = await getTickers(user);
const tickerData = await getTickerChanges(tickers);
clearTimeout(timeoutId);
renderUserPage(user, { tableData: tickerData });
}
// subscribe to realtime updates once realtime services are loaded
loadRealtimeService.then(({ subscribeToTickerChanges }) => {
unsubscribeTickerChanges = subscribeToTickerChanges(user, stockData => {
clearTimeout(timeoutId);
renderUserPage(user, { tableData: stockData })
});
});
} else {
// DON'T EDIT THIS PART, YET
}
}
- في قسم else حيث لم يتم تسجيل دخول أي مستخدم، يمكنك جلب معلومات الأسعار لجميع الأسهم باستخدام Firestore Lite، ثم عرض الصفحة، ثم الاستماع إلى تغييرات الأسعار بعد تحميل الخدمات في الوقت الفعلي:
src/main.ts
if (user) {
// DON'T EDIT THIS PART, WHICH WE JUST CHANGED ABOVE
...
} else {
// REPLACE THESE LINES
// login page
setUser(null);
// show loading screen in 500ms
const timeoutId = setTimeout(() => {
renderLoginPage('Landing page', {
loading: true,
tableData: []
});
}, 500);
// get data once if realtime services haven't been loaded
if (!getState().realtimeServicesLoaded) {
const tickerData = await getAllTickerChanges();
clearTimeout(timeoutId);
renderLoginPage('Landing page', { tableData: tickerData });
}
// subscribe to realtime updates once realtime services are loaded
loadRealtimeService.then(({ subscribeToAllTickerChanges }) => {
unsubscribeAllTickerChanges = subscribeToAllTickerChanges(stockData => {
clearTimeout(timeoutId);
renderLoginPage('Landing page', { tableData: stockData })
});
});
}
يمكنك الاطّلاع على src/main.ts للحصول على الرمز البرمجي النهائي.
التأكّد من أنّ التطبيق يعمل
- نفِّذ
npm run buildلإعادة إنشاء التطبيق. - افتح علامة تبويب متصفّح وانتقِل إلى http://localhost:8080 أو أعِد تحميل علامة التبويب الحالية.
التحقّق من حجم الحزمة
- افتح "أدوات مطوّري البرامج في Chrome".
- انتقِل إلى علامة التبويب الشبكة.
- إعادة تحميل الصفحة لالتقاط طلبات الشبكة
- ابحث عن
main.jsوتحقّق من حجمه. - أصبح حجمه الآن 115 كيلوبايت فقط (34.5 كيلوبايت مضغوط بتنسيق gzip). هذا الحجم أصغر بنسبة% 75 من حجم الحزمة الأصلي الذي كان يبلغ 446 كيلوبايت(138 كيلوبايت مضغوط بتنسيق gzip). نتيجةً لذلك، يتم تحميل الموقع الإلكتروني بسرعة أكبر من ثانيتين على شبكة الجيل الثالث، ما يؤدي إلى تحسين كبير في الأداء وتجربة المستخدم.

8. تهانينا
تهانينا، لقد نجحت في ترقية التطبيق وتقليل حجمه وتسريع أدائه.
استخدمت حِزم التوافق لترقية التطبيق جزءًا جزءًا، واستخدمت Firestore Lite لتسريع عرض الصفحة الأولي، ثم حمّلت Firestore الرئيسي بشكل ديناميكي لعرض تغييرات الأسعار.
لقد قلّلت أيضًا حجم الحزمة وحسّنت وقت تحميلها خلال هذا الدرس العملي:
main.js | حجم المرجع (كيلوبايت) | الحجم المضغوط (كيلوبايت) | مدة التحميل (بالثواني) (على شبكة الجيل الثالث البطيئة) |
v8 | 446 | 138 | 4.92 |
v9 compat | 429 | 124 | 4.65 |
الإصدار 9 فقط من Auth المعياري | 348 | 102 | 4.2 |
الإصدار 9 من النظام المعياري بالكامل | 244 | 74.6 | 3.66 |
الإصدار 9 من حزمة SDK الكاملة ذات الوحدات + Firestore lite | 117 | 34.9 | 2.88 |

أصبحت الآن على دراية بالخطوات الرئيسية المطلوبة لترقية تطبيق ويب يستخدم الإصدار 8 من حزمة تطوير البرامج (SDK) في JavaScript لمنصة Firebase إلى حزمة تطوير البرامج (SDK) الجديدة في JavaScript ذات الوحدات.