1- قبل البدء
إنّ حزمة تطوير البرامج (SDK) المكوّنة من وحدات لـ Firebase JS هي إعادة كتابة لحزمة تطوير البرامج (SDK) الحالية لـ JS، وسيتم إصدارها كإصدار رئيسي جديد. تتيح هذه الميزة للمطوّرين استبعاد الرموز البرمجية غير المستخدَمة من حزمة تطوير البرامج (SDK) لبرنامج Firebase JS من أجل إنشاء حِزم أصغر وتحقيق أداء أفضل.
يكمن الاختلاف الأكثر وضوحًا في حزمة SDK المكوّنة من وحدات JavaScript في أنّ الميزات يتم تنظيمها الآن في وظائف عائمة حرة ستستوردها، بدلاً من استخدام مساحة اسم firebase
واحدة تتضمّن كل شيء. تسمح هذه الطريقة الجديدة لتنظيم الرموز البرمجية بإزالة العناصر غير الضرورية، وسوف تتعرّف على كيفية ترقية أي تطبيق يستخدم حاليًا الإصدار 8 من حزمة تطوير البرامج (SDK) لبرنامج Firebase JavaScript إلى الحزمة الجديدة المكوّنة من وحدات.
لتسهيل عملية الترقية، يتم توفير مجموعة من حِزم التوافق. في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية استخدام حِزم التوافق لنقل التطبيق جزءًا تلو الآخر.
التطبيق الذي ستصممه
في هذا الدليل التعليمي حول الرموز البرمجية، ستنقل تدريجيًا تطبيق ويب حاليًا يتضمّن قائمة مراقبة الأسهم ويستخدم حزمة تطوير البرامج (SDK) لإصدار 8 من JavaScript إلى حزمة تطوير البرامج (SDK) الجديدة والمكوّنة من وحدات لإصدار JavaScript في ثلاث مراحل:
- ترقية التطبيق لاستخدام حِزم التوافق
- ترقية التطبيق من حِزم التوافق إلى واجهة برمجة التطبيقات المُركّبة تدريجيًا
- استخدام Firestore Lite، وهو إصدار خفيف من حزمة تطوير البرامج (SDK) لمنصّة Firestore، لتحسين أداء التطبيق بشكلٍ أكبر
تركّز ورشة رموز البرامج هذه على ترقية حزمة تطوير البرامج (SDK) لمنصّة Firebase. يتمّ التقليل من أهمية المفاهيم الأخرى ووحدات الرموز البرمجية، ويتمّ تقديمها لك لكي تتمكّن من نسخها ولصقها بسهولة.
المتطلبات
- متصفّح من اختيارك، مثل Chrome
- بيئة تطوير البرامج/محرر النصوص المفضّل لديك، مثل WebStorm أو Atom أو Sublime أو VS Code
- أداة إدارة الحِزم npm، التي تأتي عادةً مع Node.js
- نموذج الرمز البرمجي للدرس التطبيقي حول الترميز (اطّلِع على الخطوة التالية من الدرس التطبيقي حول الترميز لمعرفة كيفية الحصول على الرمز).
2- الإعداد
الحصول على الرمز
يمكنك العثور على كل ما تحتاجه لهذا المشروع في مستودع Git. للبدء، عليك الحصول على الرمز وفتحه في بيئة المطوّر المفضّلة لديك.
استنسِخ مستودع Github الخاص ببرنامج التعليم البرمجي من سطر الأوامر:
git clone https://github.com/FirebaseExtended/codelab-modular-sdk.git
بدلاً من ذلك، إذا لم يكن لديك git مثبّتًا، يمكنك تنزيل المستودع كملف ZIP وفك ضغط ملف ZIP الذي تم تنزيله.
استيراد التطبيق
- باستخدام بيئة تطوير البرامج المتكاملة، افتح دليل
codelab-modular-sdk
أو استورِده. - شغِّل
npm install
لتثبيت التبعيات المطلوبة لإنشاء التطبيق وتشغيله على الجهاز. - شغِّل
npm run build
لإنشاء التطبيق. - تشغيل
npm run serve
لبدء خادم الويب - افتح علامة تبويب في المتصفّح للانتقال إلى http://localhost:8080.
3- تحديد مرجع
ما هي نقطة البداية؟
نقطة البداية هي تطبيق قائمة مراقبة الأسهم المصمّم لهذا الدليل التعليمي حول رموز الترميز. تم تبسيط الرمز لشرح المفاهيم الواردة في هذا الدليل التعليمي حول الرموز البرمجية، ولا يتضمّن الكثير من عمليات معالجة الأخطاء. إذا اخترت إعادة استخدام أيّ من هذا الرمز في تطبيق علني، تأكَّد من معالجة أيّ أخطاء واختبار كلّ الرمز البرمجي بالكامل.
تأكَّد من أنّ كل العناصر تعمل في التطبيق:
- سجِّل الدخول بشكل مجهول باستخدام زر تسجيل الدخول في أعلى يسار الصفحة.
- بعد تسجيل الدخول، ابحث عن "NFLX" و"SBUX" و "T" وأضِفها إلى قائمة المشاهدة من خلال النقر على الزر إضافة وكتابة الأحرف والنقر على صف نتائج البحث الذي يظهر أدناه.
- أزِل سهمًا من قائمة المراقبة بالنقر على x في نهاية الصف.
- اطّلِع على آخر المعلومات في الوقت الفعلي عن سعر السهم.
- افتح "أدوات مطوّري البرامج في Chrome"، وانتقِل إلى علامة التبويب الشبكة وضَع علامة في المربّع بجانب إيقاف ذاكرة التخزين المؤقت واستخدام صفوف طلبات كبيرة. يضمن خيار إيقاف ذاكرة التخزين المؤقت تلقّي أحدث التغييرات دائمًا بعد التحديث، ويؤدي خيار استخدام صفوف طلبات كبيرة إلى عرض كلّ من الحجم المُرسَل وحجم المرجع لمرجع معيّن. في هذا الدرس التطبيقي حول الترميز، نحن مهتمون بشكل أساسي بحجم
main.js
.
- تحميل التطبيق في ظل ظروف شبكة مختلفة باستخدام ميزة "تقييد المحاكاة" ستستخدم شبكة الجيل الثالث (3G) البطيئة لقياس وقت التحميل في هذا الدليل التعليمي لأنّه يُظهر بوضوح مدى أهمية تقليل حجم الحِزمة.
يمكنك الآن البدء في نقل بيانات التطبيق إلى واجهة برمجة التطبيقات الجديدة والمكوّنة من وحدات.
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 API بسيطة نسبيًا. إنّ ترقية Firestore أكثر تعقيدًا قليلاً، وسنشرح لك كيفية إجراء ذلك في القسم التالي.
تعديل إعداد Auth
- الانتقال إلى الملف
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 | حجم المورد (بالكيلوبايت) | حجم الملف المضغوَط بتنسيق gzip (بالكيلوبايت) | مدّة التحميل (بالثواني) (عبر شبكة الجيل الثالث البطيئة) |
v8 | 446 | 138 | 4.92 |
التوافق مع الإصدار 9 | 429 | 124 | 4.65 |
المصادقة المُركّبة في الإصدار 9 فقط | 348 | 102 | 4.2 |
الإصدار 9 من الوحدات بالكامل | 244 | 74.6 | 3.66 |
الإصدار 9 من الوحدات بالكامل + Firestore lite | 117 | 34.9 | 2.88 |
تعرّفت الآن على الخطوات الرئيسية المطلوبة لترقية تطبيق ويب يستخدم الإصدار 8 من حزمة تطوير البرامج (SDK) لبرنامج Firebase JavaScript لاستخدام حزمة تطوير البرامج (SDK) الجديدة والمكوّنة من وحدات لبرنامج JavaScript.