שדרוג אפליקציית האינטרנט באמצעות מעבר ל-Firebase JS SDK המודולרי

1. לפני שמתחילים

ה-SDK המודולרי של Firebase JS הוא כתיבה מחדש של ה-SDK הקיים של JS, והוא יושק כגרסה הראשית הבאה. הוא מאפשר למפתחים להחריג קוד שלא נמצא בשימוש מ-Firebase JS SDK כדי ליצור חבילות קטנות יותר ולשפר את הביצועים.

ההבדל הבולט ביותר ב-JS SDK המודולרי הוא שעכשיו התכונות מאורגנות בפונקציות עצמאיות שצריך לייבא, ולא במרחב שמות יחיד firebase שכולל הכול. הדרך החדשה לארגון הקוד מאפשרת ניעור עצים, ובמאמר הזה נסביר איך לשדרג כל אפליקציה שמשתמשת כרגע ב-Firebase JS SDK בגרסה 8 לגרסה המודולרית החדשה.

כדי לספק תהליך שדרוג חלק, אנחנו מספקים חבילה של תאימות. ב-codelab הזה תלמדו איך להשתמש בחבילות התאימות כדי להעביר את האפליקציה חלק אחר חלק.

מה תפַתחו

ב-codelab הזה תעברו בהדרגה מאפליקציית אינטרנט קיימת של רשימת מעקב אחר מניות שמשתמשת ב-v8 JS SDK אל ה-JS SDK המודולרי החדש, בשלושה שלבים:

  • שדרוג האפליקציה כדי להשתמש בחבילות התאימות
  • שדרוג האפליקציה מחבילות התאימות למודול ה-API, שלב אחר שלב
  • שימוש ב-Firestore Lite, הטמעה קלה של Firestore SDK, כדי לשפר עוד יותר את הביצועים של האפליקציה

2d351cb47b604ad7.png

ה-codelab הזה מתמקד בשדרוג של Firebase SDK. מושגים אחרים וקטעי קוד מוצגים בקצרה, וכל מה שצריך לעשות הוא להעתיק ולהדביק אותם.

מה צריך

  • דפדפן לפי בחירתכם, כמו Chrome
  • סביבת פיתוח משולבת (IDE) או עורך טקסט לפי בחירתכם, כמו WebStorm,‏ Atom,‏ Sublime או VS Code
  • מנהל החבילות npm, שמגיע בדרך כלל עם Node.js
  • קוד לדוגמה מתוך ה-Codelab (בשלב הבא של ה-Codelab מוסבר איך לקבל את הקוד).

2. שנתחיל?

קבלת הקוד

כל מה שצריך לפרויקט הזה נמצא במאגר Git. כדי להתחיל, צריך להעתיק את הקוד ולפתוח אותו בסביבת הפיתוח המועדפת.

משכפלים את מאגר GitHub של ה-codelab משורת הפקודה:

git clone https://github.com/FirebaseExtended/codelab-modular-sdk.git

לחלופין, אם git לא מותקן, אפשר להוריד את המאגר כקובץ ZIP ולפתוח את קובץ ה-ZIP שהורדתם.

ייבוא האפליקציה

  1. באמצעות ה-IDE, פותחים או מייבאים את הספרייה codelab-modular-sdk.
  2. מריצים את npm install כדי להתקין את התלות שנדרשת ליצירת גרסת build של האפליקציה ולהרצתה באופן מקומי.
  3. מריצים את הפקודה npm run build כדי לבנות את האפליקציה.
  4. מריצים את הפקודה npm run serve כדי להפעיל את שרת האינטרנט
  5. פותחים כרטיסייה בדפדפן ועוברים אל http://localhost:8080

71a8a7d47392e8f4.png

3. הגדרת ערך בסיס

מהי נקודת ההתחלה שלך?

נקודת ההתחלה היא אפליקציה מוכנה של רשימת צפייה, שנוצרה במיוחד בשביל ה-codelab הזה. הקוד פושט כדי להמחיש את המושגים ב-codelab הזה, ואין בו הרבה טיפול בשגיאות. אם תבחרו לעשות שימוש חוזר בקוד הזה באפליקציה בסביבת הייצור, הקפידו לטפל בכל השגיאות ולבדוק את כל הקוד באופן מלא.

מוודאים שהכול פועל באפליקציה:

  1. מתחברים באופן אנונימי באמצעות לחצן ההתחברות בפינה השמאלית העליונה.
  2. אחרי שמתחברים, מחפשים את הסמלים NFLX,‏ SBUX ו-T ומוסיפים אותם לרשימת המעקב. כדי לעשות זאת, לוחצים על הלחצן הוספה, מקלידים את האותיות ולוחצים על שורת תוצאת החיפוש שמופיעה למטה.
  3. כדי להסיר מניה מרשימת המעקב, לוחצים על x בסוף השורה.
  4. צפייה בעדכונים בזמן אמת של מחיר המניה.
  5. פותחים את כלי הפיתוח ל-Chrome, עוברים לכרטיסייה Network ומסמנים את התיבות Disable cache ו-Use large request rows. האפשרות השבתת מטמון מבטיחה שנקבל תמיד את השינויים האחרונים אחרי רענון, והאפשרות שימוש בשורות בקשה גדולות גורמת לכך שבשורה יוצגו גם הגודל של המשאב וגם הגודל של המשאב שמועבר. ב-codelab הזה, אנחנו מתעניינים בעיקר בגודל של main.js.

48a096debb2aa940.png

  1. טוענים את האפליקציה בתנאי רשת שונים באמצעות הגבלת רוחב פס מדומה. ב-codelab הזה נשתמש ב-Slow 3G כדי למדוד את זמן הטעינה, כי שם גודל חבילה קטן יותר עוזר הכי הרבה.

4397cb2c1327089.png

עכשיו אפשר להתחיל להעביר את האפליקציה ל-API המודולרי החדש.

4. שימוש בחבילות התאימות

חבילות התאימות מאפשרות לשדרג לגרסה החדשה של ה-SDK בלי לשנות את כל קוד Firebase בבת אחת. אתם יכולים לשדרג אותם ל-API מודולרי בהדרגה.

בשלב הזה, תשדרגו את ספריית Firebase מגרסה 8 לגרסה החדשה ותשנו את הקוד כך שישתמש בחבילות התאימות. בשלבים הבאים נסביר איך לשדרג רק את קוד Firebase Auth כדי להשתמש קודם ב-API מודולרי, ואז לשדרג את קוד Firestore.

בסוף כל שלב, אמורה להיות לכם אפשרות לקמפל ולהפעיל את האפליקציה בלי שהיא תיפגע, ולראות ירידה בגודל חבילת האפליקציה בזמן שאנחנו מעבירים כל מוצר.

קבלת ה-SDK החדש

מחפשים את הקטע [dependencies] בקובץ package.json ומחליפים אותו בקטע הבא:

package.json

"dependencies": {
    "firebase": "^9.0.0" 
}

התקנה מחדש של יחסי התלות

שינינו את הגרסה של התלות, ולכן צריך להריץ מחדש את הפקודה npm install כדי לקבל את הגרסה החדשה של התלות.

שינוי נתיבי הייבוא

חבילות התאימות נחשפות במודול המשנה firebase/compat, ולכן נעדכן את נתיבי הייבוא בהתאם:

  1. מעבר לקובץ src/firebase.ts
  2. מחליפים את הייבוא הקיים בייבוא הבא:

src/firebase.ts

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

אימות פעולת האפליקציה

  1. מריצים את הפקודה npm run build כדי לבנות מחדש את האפליקציה.
  2. פותחים כרטיסייה בדפדפן בכתובת http://localhost:8080 או מרעננים את הכרטיסייה הקיימת.
  3. מפעילים את האפליקציה. הכול אמור לפעול.

5. שדרוג האימות לשימוש ב-API מודולרי

אפשר לשדרג את מוצרי Firebase בכל סדר. ב-codelab הזה, נשדרג קודם את Auth כדי ללמוד את המושגים הבסיסיים, כי Auth API הוא פשוט יחסית. שדרוג של Firestore הוא תהליך מורכב יותר, ובשלב הבא נסביר איך לעשות את זה.

עדכון של אתחול האימות

  1. מעבר לקובץ src/firebase.ts
  2. מוסיפים את שורת הייבוא הבאה:

src/firebase.ts

import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
  1. מחיקת import ‘firebase/compat/auth'.
  2. מחליפים את export const firebaseAuth = app.auth(); ב:

src/firebase.ts

export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
  1. מסירים את export type User = firebase.User; בסוף הקובץ. User ייצא ישירות ב-src/auth.ts, שאותו תשנה בהמשך.

עדכון קוד האימות

  1. מעבר לקובץ src/auth.ts
  2. מוסיפים את שורות הייבוא הבאות לחלק העליון של הקובץ:

src/auth.ts

import { 
    signInAnonymously, 
    signOut,
    onAuthStateChanged,
    User
} from 'firebase/auth';
  1. הסרת User מהחשבון import { firebaseAuth, User } from './firebase'; כי כבר ייבאת User מ-‘firebase/auth'.
  2. מעדכנים את הפונקציות לשימוש ב-API המודולרי.

כפי שראיתם קודם כשעדכנו את הצהרת הייבוא, חבילות בגרסה 9 מאורגנות סביב פונקציות שאפשר לייבא, בניגוד לממשקי API בגרסה 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';

אימות פעולת האפליקציה

  1. מריצים את הפקודה npm run build כדי לבנות מחדש את האפליקציה.
  2. פותחים כרטיסייה בדפדפן בכתובת http://localhost:8080 או מרעננים את הכרטיסייה הקיימת.
  3. מפעילים את האפליקציה. הכול אמור לפעול.

בדיקת גודל החבילה

  1. פותחים את כלי הפיתוח ל-Chrome.
  2. עוברים לכרטיסייה רשת.
  3. כדי לתעד את בקשות הרשת, צריך לרענן את הדף.
  4. מחפשים את הקובץ main.js ובודקים את הגודל שלו. הקטנתם את גודל החבילה ב-100KB (36KB אחרי דחיסה), כלומר הקטנתם את הגודל בכ-22% על ידי שינוי של כמה שורות קוד בלבד. האתר נטען גם 0.75 שניות מהר יותר בחיבור 3G איטי.

2e4eafaf66cd829b.png

6. שדרוג אפליקציית Firebase ו-Firestore לשימוש בממשק API מודולרי

עדכון ההפעלה של Firebase

  1. מעבר לקובץ src/firebase.ts.
  2. מחליפים את import firebase from ‘firebase/compat/app'; ב:

src/firebase.ts

import { initializeApp } from 'firebase/app';
  1. מחליפים את 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

  1. באותו קובץ src/firebase.ts, מחליפים את import 'firebase/compat/firestore'; ב-

src/firebase.ts

import { getFirestore } from 'firebase/firestore';
  1. מחליפים את export const firestore = app.firestore(); ב:

src/firebase.ts

export const firestore = getFirestore();
  1. הסרת כל השורות אחרי "export const firestore = ..."

עדכון של ייבוא

  1. פתיחת הקובץ src/services.ts.
  2. הסרת FirestoreFieldPath, ‏ FirestoreFieldValue ו-QuerySnapshot מהייבוא. הייבוא מ-'./firebase' אמור להיראות עכשיו כך:

src/services.ts

import { firestore } from './firebase';
  1. מייבאים את הפונקציות והסוגים שבהם רוצים להשתמש בחלק העליון של הקובץ:
    **src/services.ts**
import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove, 
    onSnapshot, 
    query, 
    where, 
    documentId, 
    QuerySnapshot
} from 'firebase/firestore';
  1. יוצרים הפניה לאוסף שמכיל את כל הטיקרים:

src/services.ts

const tickersCollRef = collection(firestore, 'current');
  1. משתמשים ב-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 });
}

Update 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()‎

  1. משתמשים ב-doc() כדי ליצור הפניה למסמך ברשימת המעקב של המשתמש, ואז משתמשים ב-onSnapshot() כדי לעקוב אחרי שינויים ברשימת המעקב:

src/services.ts

const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
   /* subscribe to ticker price changes */
});
  1. אחרי שמוסיפים את הטיקרים לרשימת המעקב, משתמשים ב-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);
   });
}

אימות פעולת האפליקציה

  1. מריצים את הפקודה npm run build כדי לבנות מחדש את האפליקציה.
  2. פותחים כרטיסייה בדפדפן בכתובת http://localhost:8080 או מרעננים את הכרטיסייה הקיימת.
  3. מפעילים את האפליקציה. הכול אמור לפעול.

בדיקת גודל החבילה

  1. פותחים את כלי הפיתוח ל-Chrome.
  2. עוברים לכרטיסייה רשת.
  3. כדי לתעד את בקשות הרשת, צריך לרענן את הדף.
  4. מחפשים את main.js ובודקים את הגודל שלו. משווים שוב לגודל החבילה המקורי – הקטנו את גודל החבילה ביותר מ-200KB (63.8KB אחרי דחיסה), או ב-50%, מה שאומר שזמן הטעינה מהיר יותר ב-1.3 שניות!

7660cdc574ee8571.png

7. שימוש ב-Firestore Lite כדי להאיץ את הרינדור הראשוני של הדף

מה זה Firestore Lite?

ה-SDK של Firestore מציע שמירה מורכבת במטמון, סטרימינג בזמן אמת, אחסון קבוע, סנכרון אופליין בכמה כרטיסיות, ניסיונות חוזרים, מקביליות אופטימית ועוד הרבה יותר, ולכן הוא גדול למדי. אבל יכול להיות שתרצו פשוט לקבל את הנתונים פעם אחת, בלי להשתמש בתכונות המתקדמות. לכן, ב-Firestore יצרנו פתרון פשוט וקל משקל – חבילה חדשה לגמרי בשם Firestore Lite.

מקרה שימוש מצוין ב-Firestore Lite הוא אופטימיזציה של הביצועים של העיבוד הראשוני של הדף, שבו צריך לדעת רק אם משתמש מחובר או לא, ואז לקרוא נתונים מ-Firestore כדי להציג אותם.

בשלב הזה נסביר איך להשתמש ב-Firestore lite כדי להקטין את גודל החבילה, וכך להאיץ את הטעינה הראשונית של הדף. לאחר מכן נטען את Firestore SDK הראשי באופן דינמי כדי להירשם לעדכונים בזמן אמת.

תבצעו רפקטורינג של הקוד כדי:

  1. מעבירים שירותים בזמן אמת לקובץ נפרד, כדי שיהיה אפשר לטעון אותם באופן דינמי באמצעות ייבוא דינמי.
  2. יוצרים פונקציות חדשות כדי להשתמש ב-Firestore Lite לאחזור רשימת המניות למעקב ומחירי המניות.
  3. משתמשים בפונקציות החדשות של Firestore Lite כדי לאחזר נתונים לצורך העיבוד הראשוני של הדף, ואז טוענים באופן דינמי את השירותים בזמן אמת כדי להאזין לעדכונים בזמן אמת.

העברת שירותים בזמן אמת לקובץ חדש

  1. יצירת קובץ חדש בשם src/services.realtime.ts.
  2. מעבירים את הפונקציות subscribeToTickerChanges() ו-subscribeToAllTickerChanges() מ-src/services.ts לקובץ החדש.
  3. מוסיפים את ההצהרות הנדרשות על ייבוא בחלק העליון של הקובץ החדש.

עדיין צריך לבצע כמה שינויים:

  1. קודם צריך ליצור מופע של Firestore מ-Firestore SDK הראשי בחלק העליון של הקובץ, כדי להשתמש בו בפונקציות. אי אפשר לייבא את מופע Firestore מ-firebase.ts כאן כי בעוד כמה שלבים תשנו אותו למופע Firestore Lite, שישמש רק לעיבוד הראשוני של הדף.
  2. שנית, מסירים את המשתנה 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 לאחזור נתונים

  1. פתיחה של src/services.ts.
  2. כדי לשנות את נתיב הייבוא מ-‘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';
  1. מוסיפים פונקציות לאחזור הנתונים שנדרשים לטעינה הראשונית של הדף באמצעות 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);
}
  1. פותחים את src/firebase.ts ומשנים את נתיב הייבוא מ-‘firebase/firestore' ל-‘firebase/firestore/lite':

src/firebase.ts

import { getFirestore } from 'firebase/firestore/lite';

איך משלבים את הכול

  1. פתיחה של src/main.ts.
  2. תצטרכו את הפונקציות החדשות שיצרתם כדי לאחזר נתונים עבור העיבוד הראשוני של הדף, ועוד כמה פונקציות עזר לניהול מצב האפליקציה. לכן צריך לעדכן את הייבוא:

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';
  1. טוענים את src/services.realtime באמצעות ייבוא דינמי בחלק העליון של הקובץ. המשתנה loadRealtimeService הוא הבטחה שתמומש עם שירותים בזמן אמת אחרי שהקוד ייטען. בהמשך תשתמשו בו כדי להירשם לעדכונים בזמן אמת.

src/main.ts

const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
   setRealtimeServicesLoaded(true);
});
  1. משנים את הקריאה החוזרת (callback) של onUserChange() לפונקציה async, כדי שנוכל להשתמש ב-await בגוף הפונקציה:

src/main.ts

onUserChange(async user => {
 // callback body
});
  1. עכשיו מאחזרים את הנתונים כדי לבצע את הטיוח הראשוני של הדף באמצעות הפונקציות החדשות שיצרנו בשלב הקודם.

ב-callback‏ 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   
   }
}
  1. בבלוק 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.

אימות פעולת האפליקציה

  1. מריצים את הפקודה npm run build כדי לבנות מחדש את האפליקציה.
  2. פותחים כרטיסייה בדפדפן בכתובת http://localhost:8080 או מרעננים את הכרטיסייה הקיימת.

בדיקת גודל החבילה

  1. פותחים את כלי הפיתוח ל-Chrome.
  2. עוברים לכרטיסייה רשת.
  3. רענון הדף כדי לתעד בקשות רשת
  4. מחפשים את main.js ובודקים את הגודל שלו.
  5. עכשיו הוא רק 115KB (34.5KB אחרי דחיסה). זהו גודל קטן ב-75% מגודל החבילה המקורי, שהיה ‎446 KB(‎138 KB אחרי דחיסה ב-gzip). כתוצאה מכך, האתר נטען במהירות גבוהה יותר של יותר מ-2 שניות בחיבור 3G – שיפור משמעותי בביצועים ובחוויית המשתמש!

9ea7398a8c8ef81b.png

8. מזל טוב

הצלחת לשדרג את האפליקציה ולהקטין אותה, ועכשיו היא מהירה יותר.

השתמשתם בחבילות התאימות כדי לשדרג את האפליקציה חלק אחר חלק, והשתמשתם ב-Firestore Lite כדי להאיץ את הטעינה הראשונית של הדף, ואז טענתם באופן דינמי את Firestore הראשי כדי להזרים שינויים במחירים.

במהלך ה-codelab הזה, הקטנתם גם את גודל החבילה ושיפרתם את זמן הטעינה שלה:

main.js

גודל המשאב (KB)

גודל אחרי gzip (ב-KB)

זמן טעינה (בשניות) (בחיבור 3G איטי)

v8

446

138

4.92

תאימות לגרסה 9

429

124

4.65

מודול Auth בגרסה 9 בלבד

348

102

‫4.2

גרסה 9 מודולרית לחלוטין

244

74.6

3.66

גרסה 9 מודולרית לחלוטין + Firestore lite

117

34.9

2.88

32a71bd5a774e035.png

עכשיו אתם יודעים מהם השלבים העיקריים שנדרשים לשדרוג אפליקציית אינטרנט שמשתמשת ב-Firebase JS SDK בגרסה 8, כדי להשתמש ב-JS SDK המודולרי החדש.

קריאה נוספת

מאמרי עזרה