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

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

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

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

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

מה תפַתחו

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

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

2d351cb47b604ad7.png

בקודלאב הזה נסביר איך לשדרג את 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. פותחים או מייבאים את התיקייה codelab-modular-sdk באמצעות סביבת הפיתוח המשולבת (IDE).
  2. מריצים את הפקודה npm install כדי להתקין את יחסי התלות שנדרשים ליצירה ולהפעלה של האפליקציה באופן מקומי.
  3. מריצים את הפקודה npm run build כדי ליצור את האפליקציה.
  4. מריצים את הפקודה npm run serve כדי להפעיל את שרת האינטרנט
  5. פותחים כרטיסייה בדפדפן ומזינים את הכתובת http://localhost:8080.

71a8a7d47392e8f4.png

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

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

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

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

  1. מתחברים באופן אנונימי באמצעות הלחצן login (התחברות) בפינה השמאלית העליונה.
  2. אחרי הכניסה לחשבון, מחפשים את 'NFLX', 'SBUX' ו-'T' ומוסיפים אותם לרשימת הצפייה. לשם כך, לוחצים על הלחצן הוספה, מקלידים את האותיות ולוחצים על השורה של תוצאת החיפוש שמופיעה למטה.
  3. כדי להסיר מניה מרשימת המעקב, לוחצים על x בסוף השורה.
  4. לצפות בעדכונים בזמן אמת של מחיר המניה.
  5. פותחים את כלי הפיתוח ל-Chrome, עוברים לכרטיסייה רשת ומסמנים את התיבות השבתה של המטמון ושימוש בשורות בקשה גדולות. השבתת המטמון מוודאת שתמיד יתקבלו השינויים האחרונים אחרי רענון, והאפשרות שימוש בשורות בקשה גדולות תגרום להצגת השורה גם בגודל המשודר וגם בגודל המשאב של המשאב. בקודלאב הזה, אנחנו מתעניינים בעיקר בגודל של main.js.

48a096debb2aa940.png

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

4397cb2c1327089.png

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

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

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

בשלב הזה, משדרגים את ספריית Firebase מגרסה 8 לגרסה החדשה, ומשנים את הקוד כך שישתמש בחבילות התאימות. בשלבים הבאים נסביר איך לשדרג רק את קוד האימות של Firebase כדי להשתמש קודם ב-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 מורכב יותר, ונסביר איך עושים את זה בהמשך.

עדכון של Auth initialization

  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 שמבוססים על שם תחום ושירות עם שרשור נקודות. הארגון החדש של הקוד מאפשר להסיר קוד שלא נעשה בו שימוש, כי הוא מאפשר לכלים ל-build לנתח איזה קוד נמצא בשימוש ואיזה לא.

בגרסה 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. עוברים לכרטיסייה Network (רשת).
  3. צריך לרענן את הדף כדי לתעד את בקשות הרשת.
  4. מחפשים את הקובץ main.js ובודקים את הגודל שלו. שיניתם רק כמה שורות קוד והקטנתם את גודל החבילה ב-100KB (36KB ב-Gzip), או בכ-22%. בנוסף, האתר נטען מהר יותר ב-0.75 שניות בחיבור איטי מסוג 3G.

2e4eafaf66cd829b.png

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

עדכון ההפעלה של 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. באותו קובץ, מחליפים את import 'firebase/compat/firestore'; ב-import 'firebase/compat/firestore';src/firebase.ts,

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 });
}

עדכון 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);
  });

ההטמעה המלאה זמינה במאמר subscriptionToTickerChanges().

עדכון 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. עוברים לכרטיסייה Network (רשת).
  3. צריך לרענן את הדף כדי לתעד בקשות רשת.
  4. מחפשים את main.js ובודקים את הגודל שלו. שוב, אפשר להשוות את הגודל של החבילה המאוחדת לגודל המקורי שלה – הפחתנו את גודל החבילה ב-200KB (63.8KB בפורמט GZIP), כלומר ב-50%, וכתוצאה מכך זמן הטעינה קצר ב-1.3 שניות!

7660cdc574ee8571.png

7. איך להשתמש ב-Firestore Lite כדי להאיץ את העיבוד הראשוני של הדפים

מהו Firestore Lite?

ה-Firestore SDK כולל שמירה מורכבת במטמון, סטרימינג בזמן אמת, אחסון מתמיד, סנכרון אופליין במספר כרטיסיות, ניסיונות חוזרים, בו-זמניות אופטימית ועוד הרבה יותר, ולכן גודלו די גדול. אבל יכול להיות שתרצו פשוט לקבל את הנתונים פעם אחת, בלי שתצטרכו להשתמש בתכונות המתקדמות. במקרים כאלה, יצרנו ב-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 מה-SDK הראשי של Firestore בחלק העליון של הקובץ, כדי להשתמש בה בפונקציות. לא ניתן לייבא את המכונה של 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. משנים את הקריאה החוזרת של 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. בבלוק האחר שבו אף משתמש לא מחובר, מאחזרים את פרטי המחירים של כל המניות באמצעות 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. עוברים לכרטיסייה Network (רשת).
  3. צריך לרענן את הדף כדי לתעד את בקשות הרשת
  4. מחפשים את main.js ובודקים את הגודל שלו.
  5. עכשיו הוא רק 115KB (34.5KB ב-Gzip). הגודל הזה קטן ב-75% מגודל החבילה המקורי שהיה 446KB(138KB gzipped)! כתוצאה מכך, האתר נטען מהר יותר ביותר מ-2 שניות בחיבור 3G – שיפור משמעותי בביצועים ובחוויית המשתמש!

9ea7398a8c8ef81b.png

8. מזל טוב

מזל טוב, שדרגת את האפליקציה והפכת אותה לקטינה יותר ומהירה יותר!

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

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

main.js

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

גודל gzip (kb)

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

גרסה 8

446

138

4.92

v9 compat

429

124

4.65

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

348

102

4.2

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

244

74.6

3.66

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

117

34.9

2.88

32a71bd5a774e035.png

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

מקורות מידע נוספים

מסמכי עזר