Web-App mit dem modularen Firebase JS SDK optimieren

1. Hinweis

Das modulare Firebase JS SDK ist eine Überarbeitung des bestehenden JS SDK und wird als nächste Hauptversion veröffentlicht. So können Entwickler ungenutzten Code aus dem Firebase JS SDK ausschließen, um kleinere Bundles zu erstellen und eine bessere Leistung zu erzielen.

Der auffälligste Unterschied im modularen JS‑SDK besteht darin, dass Funktionen jetzt in kostenlos schwebenden Funktionen organisiert sind, die Sie importieren, anstatt in einem einzelnen firebase-Namespace, der alles enthält. Diese neue Art der Codeorganisation ermöglicht das Tree Shaking. In diesem Artikel erfahren Sie, wie Sie eine App, die derzeit das v8 Firebase JS SDK verwendet, auf das neue modulare SDK umstellen.

Um einen reibungslosen Upgrade-Prozess zu ermöglichen, wird eine Reihe von Kompatibilitätspaketen bereitgestellt. In diesem Codelab erfahren Sie, wie Sie die Kompatibilitätspakete verwenden, um die App nach und nach zu portieren.

Umfang

In diesem Codelab migrieren Sie eine bestehende Webanwendung für die Aktienbeobachtung, die das v8 JS SDK verwendet, in drei Phasen zum neuen modularen JS SDK:

  • App aktualisieren, um die Kompatibilitätspakete zu verwenden
  • App schrittweise von den Kompatibilitätspaketen auf die modulare API umstellen
  • Verwenden Sie Firestore Lite, eine schlanke Implementierung des Firestore SDK, um die Leistung der App weiter zu verbessern.

2d351cb47b604ad7.png

In diesem Codelab geht es um das Aktualisieren des Firebase SDK. Auf andere Konzepte und Codeblöcke wird nicht genauer eingegangen und entsprechende Codeblöcke können Sie einfach kopieren und einfügen.

Voraussetzungen

  • Ein Browser Ihrer Wahl, z. B. Chrome
  • Die IDE oder der Texteditor Ihrer Wahl, z. B. WebStorm, Atom, Sublime oder VS Code
  • Der Paketmanager npm, der normalerweise mit Node.js geliefert wird
  • Der Beispielcode des Codelabs (Informationen zum Abrufen des Codes finden Sie im nächsten Schritt des Codelabs).

2. Einrichten

Code abrufen

Alles, was Sie für dieses Projekt benötigen, befindet sich in einem Git-Repository. Als Erstes müssen Sie den Code abrufen und in Ihrer bevorzugten Entwicklungsumgebung öffnen.

Klonen Sie das GitHub-Repository des Codelabs über die Befehlszeile:

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

Wenn Sie Git nicht installiert haben, können Sie das Repository auch als ZIP-Datei herunterladen und die heruntergeladene ZIP-Datei entpacken.

App importieren

  1. Öffnen oder importieren Sie das Verzeichnis codelab-modular-sdk in Ihrer IDE.
  2. Führen Sie npm install aus, um die Abhängigkeiten zu installieren, die zum lokalen Erstellen und Ausführen der App erforderlich sind.
  3. Führen Sie npm run build aus, um die App zu erstellen.
  4. Führen Sie npm run serve aus, um den Webserver zu starten.
  5. Öffnen Sie einen Tab im Browser und rufen Sie http://localhost:8080 auf.

71a8a7d47392e8f4.png

3. Baseline festlegen

Wo möchten Sie starten?

Ausgangspunkt ist eine Aktien-Beobachtungslisten-App, die für dieses Codelab entwickelt wurde. Der Code wurde vereinfacht, um die Konzepte in diesem Codelab zu veranschaulichen. Er enthält nur wenig Fehlerbehandlung. Wenn Sie diesen Code in einer Produktions-App wiederverwenden möchten, müssen Sie alle Fehler abfangen und den gesamten Code gründlich testen.

Prüfen Sie, ob alles in der App funktioniert:

  1. Melden Sie sich anonym über die Schaltfläche Anmelden rechts oben an.
  2. Suchen Sie nach der Anmeldung nach „NFLX“, „SBUX“ und „T“ und fügen Sie die Aktien der Beobachtungsliste hinzu. Klicken Sie dazu auf die Schaltfläche Hinzufügen, geben Sie die Buchstaben ein und klicken Sie auf die Suchergebniszeile, die unten angezeigt wird.
  3. Wenn Sie eine Aktie aus der Beobachtungsliste entfernen möchten, klicken Sie auf das x am Ende der Zeile.
  4. Aktualisierungen des Aktienkurses in Echtzeit ansehen
  5. Öffnen Sie die Chrome-Entwicklertools, rufen Sie den Tab Netzwerk auf und aktivieren Sie Cache deaktivieren und Große Anfragezeilen verwenden. Wenn Sie Cache deaktivieren auswählen, werden nach einer Aktualisierung immer die neuesten Änderungen abgerufen. Wenn Sie Große Anfragezeilen verwenden auswählen, werden in der Zeile sowohl die übertragene Größe als auch die Ressourcengröße für eine Ressource angezeigt. In diesem Codelab konzentrieren wir uns hauptsächlich auf die Größe von main.js.

48a096debb2aa940.png

  1. Laden Sie die App unter verschiedenen Netzwerkbedingungen mit simulierter Drosselung. In diesem Codelab verwenden Sie Slow 3G, um die Ladezeit zu messen, da eine kleinere Bundle-Größe hier am meisten hilft.

4397cb2c1327089.png

Beginnen Sie jetzt mit der Migration der App zur neuen modularen API.

4. Kompatibilitätspakete verwenden

Mit den Kompatibilitätspaketen können Sie ein Upgrade auf die neue SDK-Version durchführen, ohne den gesamten Firebase-Code auf einmal zu ändern. Sie können sie nach und nach auf die modulare API umstellen.

In diesem Schritt aktualisieren Sie die Firebase-Bibliothek von Version 8 auf die neue Version und ändern den Code, damit die Kompatibilitätspakete verwendet werden. In den folgenden Schritten erfahren Sie, wie Sie zuerst nur den Firebase Auth-Code aktualisieren, um die modulare API zu verwenden, und dann den Firestore-Code.

Am Ende jedes Schritts sollten Sie die App ohne Fehler kompilieren und ausführen können. Außerdem sollte die Bundle-Größe sinken, wenn wir die einzelnen Produkte migrieren.

Neues SDK herunterladen

Suchen Sie im package.json nach dem Abschnitt „dependencies“ und ersetzen Sie ihn durch Folgendes:

package.json

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

Abhängigkeiten neu installieren

Da wir die Version der Abhängigkeit geändert haben, müssen wir npm install noch einmal ausführen, um die neue Version der Abhängigkeit zu erhalten.

Importpfade ändern

Die Kompatibilitätspakete sind im Untermodul firebase/compat verfügbar. Wir aktualisieren die Importpfade entsprechend:

  1. Zur Datei src/firebase.ts
  2. Ersetzen Sie die vorhandenen Importe durch die folgenden:

src/firebase.ts

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

Funktionsfähigkeit der App überprüfen

  1. Führen Sie npm run build aus, um die App neu zu erstellen.
  2. Öffnen Sie einen Browser-Tab für http://localhost:8080 oder aktualisieren Sie den vorhandenen Tab.
  3. Probieren Sie die App aus. Alles sollte noch funktionieren.

5. Auth für die Verwendung der modularen API aktualisieren

Sie können Firebase-Produkte in beliebiger Reihenfolge upgraden. In diesem Codelab aktualisieren Sie zuerst die Auth API, um die grundlegenden Konzepte kennenzulernen, da die Auth API relativ einfach ist. Das Upgrade von Firestore ist etwas aufwendiger. Im nächsten Schritt erfahren Sie, wie Sie es durchführen.

Auth-Initialisierung aktualisieren

  1. Zur Datei src/firebase.ts
  2. Fügen Sie den folgenden Import hinzu:

src/firebase.ts

import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
  1. import ‘firebase/compat/auth'. löschen
  2. Ersetzen Sie export const firebaseAuth = app.auth(); durch:

src/firebase.ts

export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
  1. Entfernen Sie export type User = firebase.User; am Ende der Datei. User wird direkt in src/auth.ts exportiert, das Sie als Nächstes ändern.

Autorisierungscode aktualisieren

  1. Zur Datei src/auth.ts
  2. Fügen Sie oben in der Datei die folgenden Importe hinzu:

src/auth.ts

import { 
    signInAnonymously, 
    signOut,
    onAuthStateChanged,
    User
} from 'firebase/auth';
  1. Entfernen Sie User aus import { firebaseAuth, User } from './firebase';, da Sie User bereits aus ‘firebase/auth'. importiert haben.
  2. Funktionen für die Verwendung der modularen API aktualisieren

Wie Sie bereits beim Aktualisieren der Importanweisung gesehen haben, sind Pakete in Version 9 nach Funktionen organisiert, die Sie importieren können. Die APIs in Version 8 basieren dagegen auf einem durch Punkte verketteten Namespace- und Dienstmuster. Diese neue Organisation des Codes ermöglicht das Entfernen von nicht verwendetem Code, da Build-Tools analysieren können, welcher Code verwendet wird und welcher nicht.

In Version 9 werden Dienste als erstes Argument an die Funktionen übergeben. Dienste sind die Objekte, die Sie durch die Initialisierung eines Firebase-Dienstes erhalten, z.B. das Objekt, das von getAuth() oder initializeAuth() zurückgegeben wird. Sie enthalten den Status eines bestimmten Firebase-Dienstes und die Funktion verwendet den Status, um ihre Aufgaben auszuführen. Wir wenden dieses Muster an, um die folgenden Funktionen zu implementieren:

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';

Funktionsfähigkeit der App überprüfen

  1. Führen Sie npm run build aus, um die App neu zu erstellen.
  2. Öffnen Sie einen Browsertab mit http://localhost:8080 oder aktualisieren Sie den vorhandenen Tab.
  3. Probieren Sie die App aus. Alles sollte noch funktionieren.

Bundle-Größe prüfen

  1. Öffnen Sie die Chrome-Entwicklertools.
  2. Wechseln Sie zum Tab Netzwerk.
  3. Aktualisieren Sie die Seite, um Netzwerkanfragen zu erfassen.
  4. Suchen Sie nach „main.js“ und prüfen Sie die Größe. Sie haben die Bundle-Größe durch Ändern von nur wenigen Codezeilen um 100 KB (36 KB komprimiert) reduziert, was einer Verkleinerung um etwa 22% entspricht. Die Website lädt auch bei einer langsamen 3G-Verbindung 0,75 Sekunden schneller.

2e4eafaf66cd829b.png

6. Firebase-App und Firestore für die Verwendung der modularen API aktualisieren

Firebase-Initialisierung aktualisieren

  1. Zur Datei src/firebase.ts.
  2. Ersetzen Sie import firebase from ‘firebase/compat/app'; durch:

src/firebase.ts

import { initializeApp } from 'firebase/app';
  1. Ersetzen Sie const app = firebase.initializeApp({...}); durch:

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-Initialisierung aktualisieren

  1. Ersetzen Sie in derselben Datei src/firebase.ts, die Variable import 'firebase/compat/firestore'; durch

src/firebase.ts

import { getFirestore } from 'firebase/firestore';
  1. Ersetzen Sie export const firestore = app.firestore(); durch:

src/firebase.ts

export const firestore = getFirestore();
  1. Entferne alle Zeilen nach „export const firestore = ...“.

Importe aktualisieren

  1. Datei src/services.ts. öffnen
  2. Entfernen Sie FirestoreFieldPath, FirestoreFieldValue und QuerySnapshot aus dem Import. Der Import aus './firebase' sollte jetzt so aussehen:

src/services.ts

import { firestore } from './firebase';
  1. Importieren Sie die Funktionen und Typen, die Sie verwenden möchten, oben in der Datei:
    **src/services.ts**
import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove, 
    onSnapshot, 
    query, 
    where, 
    documentId, 
    QuerySnapshot
} from 'firebase/firestore';
  1. Erstellen Sie eine Referenz auf die Sammlung, die alle Tickersymbole enthält:

src/services.ts

const tickersCollRef = collection(firestore, 'current');
  1. Verwenden Sie getDocs(), um alle Dokumente aus der Sammlung abzurufen:

src/services.ts

const tickers = await getDocs(tickersCollRef);

Den fertigen Code finden Sie unter search().

addToWatchList() aktualisieren

Verwenden Sie doc(), um einen Dokumentverweis auf die Beobachtungsliste des Nutzers zu erstellen, und fügen Sie dann mit setDoc() und arrayUnion() ein Ticker-Symbol hinzu:

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

Entfernen Sie einen Ticker aus der Merkliste eines Nutzers mit setDoc() und 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 });
}

Update subscribeToTickerChanges()

  1. Verwende doc(), um zuerst einen Dokumentverweis auf die Beobachtungsliste des Nutzers zu erstellen, und höre dann mit onSnapshot() auf Änderungen der Beobachtungsliste:

src/services.ts

const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
   /* subscribe to ticker price changes */
});
  1. Sobald sich die Tickersymbole auf der Beobachtungsliste befinden, können Sie mit query() eine Abfrage erstellen, um die Preise abzurufen, und mit onSnapshot() auf Preisänderungen reagieren:

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

Die vollständige Implementierung finden Sie unter subscribeToTickerChanges().

Update subscribeToAllTickerChanges()

Zuerst verwenden Sie collection(), um einen Verweis auf die Sammlung zu erstellen, die Preise für alle Tickersymbole enthält. Anschließend verwenden Sie onSnapshot(), um auf Preisänderungen zu warten:

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

Funktionsfähigkeit der App überprüfen

  1. Führen Sie npm run build aus, um die App neu zu erstellen.
  2. Öffnen Sie einen Browsertab mit http://localhost:8080 oder aktualisieren Sie den vorhandenen Tab.
  3. Probieren Sie die App aus. Alles sollte noch funktionieren.

Bundle-Größe prüfen

  1. Öffnen Sie die Chrome-Entwicklertools.
  2. Wechseln Sie zum Tab Netzwerk.
  3. Aktualisieren Sie die Seite, um Netzwerkanfragen zu erfassen.
  4. Suchen Sie nach main.js und prüfen Sie die Größe. Vergleichen Sie sie noch einmal mit der ursprünglichen Bundle-Größe.Wir haben die Bundle-Größe um über 200 KB (63,8 KB komprimiert) oder 50% reduziert, was einer um 1,3 Sekunden schnelleren Ladezeit entspricht.

7660cdc574ee8571.png

7. Firestore Lite verwenden, um das erste Seitenrendering zu beschleunigen

Was ist Firestore Lite?

Das Firestore SDK bietet komplexes Caching, Echtzeit-Streaming, persistenten Speicher, Offline-Synchronisierung für mehrere Tabs, Wiederholungsversuche, optimistische Parallelität und vieles mehr. Daher ist es recht groß. Vielleicht möchten Sie die Daten aber auch nur einmal abrufen, ohne die erweiterten Funktionen zu nutzen. Für diese Fälle hat Firestore eine einfache und schlanke Lösung entwickelt: ein brandneues Paket namens Firestore Lite.

Ein hervorragender Anwendungsfall für Firestore Lite ist die Optimierung der Leistung des ersten Seitenrenderings, bei dem Sie nur wissen müssen, ob ein Nutzer angemeldet ist oder nicht, und dann einige Daten aus Firestore lesen, um sie anzuzeigen.

In diesem Schritt erfahren Sie, wie Sie Firestore Lite verwenden, um die Bundle-Größe zu reduzieren und das erste Seitenrendering zu beschleunigen. Anschließend laden Sie das Haupt-Firestore-SDK dynamisch, um Echtzeitaktualisierungen zu abonnieren.

Sie werden den Code umgestalten, um:

  1. Verschieben Sie Echtzeitdienste in eine separate Datei, damit sie mit dem dynamischen Import dynamisch geladen werden können.
  2. Neue Funktionen erstellen, um mit Firestore Lite Watchlist und Aktienkurse abzurufen
  3. Verwenden Sie die neuen Firestore Lite-Funktionen, um Daten für das anfängliche Seitenrendering abzurufen, und laden Sie dann die Echtzeitdienste dynamisch, um auf Echtzeitupdates zu warten.

Echtzeitdienste in eine neue Datei verschieben

  1. Erstellen Sie eine neue Datei mit dem Namen src/services.realtime.ts..
  2. Verschieben Sie die Funktionen subscribeToTickerChanges() und subscribeToAllTickerChanges() aus src/services.ts in die neue Datei.
  3. Fügen Sie oben in der neuen Datei die erforderlichen Importe hinzu.

Sie müssen hier noch einige Änderungen vornehmen:

  1. Erstellen Sie zuerst oben in der Datei, die in den Funktionen verwendet werden soll, eine Firestore-Instanz aus dem Haupt-Firestore SDK. Sie können die Firestore-Instanz nicht aus firebase.ts importieren, da Sie sie in wenigen Schritten in eine Firestore Lite-Instanz ändern, die nur für das erste Seitenrendering verwendet wird.
  2. Entfernen Sie als Nächstes die Variable firstload und den zugehörigen if-Block. Ihre Funktionen werden in neue Funktionen verschoben, die Sie im nächsten Schritt erstellen.

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 zum Abrufen von Daten verwenden

  1. src/services.ts. öffnen
  2. Ändern Sie den Importpfad von ‘firebase/firestore' zu ‘firebase/firestore/lite',, fügen Sie getDoc hinzu und entfernen Sie onSnapshot aus der Importliste.:

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. Fügen Sie Funktionen hinzu, um Daten abzurufen, die für das erste Seitenrendering mit Firestore Lite erforderlich sind:

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. Öffnen Sie src/firebase.ts und ändern Sie den Importpfad von ‘firebase/firestore' in ‘firebase/firestore/lite':.

src/firebase.ts

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

Alles zusammenfügen

  1. src/main.ts. öffnen
  2. Sie benötigen die neu erstellten Funktionen, um Daten für das erste Rendern der Seite abzurufen, sowie einige Hilfsfunktionen zum Verwalten des App-Status. Aktualisieren Sie nun die Importe:

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. Laden Sie src/services.realtime mit einem dynamischen Import oben in der Datei. Die Variable loadRealtimeService ist ein Promise, das mit den Echtzeitdiensten aufgelöst wird, sobald der Code geladen ist. Sie benötigen sie später, um Echtzeit-Updates zu abonnieren.

src/main.ts

const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
   setRealtimeServicesLoaded(true);
});
  1. Ändern Sie den Callback von onUserChange() in eine async-Funktion, damit wir await im Funktionsrumpf verwenden können:

src/main.ts

onUserChange(async user => {
 // callback body
});
  1. Rufen Sie nun die Daten ab, um die erste Seite mit den neuen Funktionen zu rendern, die wir im vorherigen Schritt erstellt haben.

Suchen Sie im onUserChange()-Callback nach der if-Bedingung, unter der ein Nutzer angemeldet ist, und kopieren Sie den Code innerhalb der if-Anweisung:

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. Im else-Block, in dem kein Nutzer angemeldet ist, werden Preisinformationen für alle Aktien mit Firestore Lite abgerufen, die Seite wird gerendert und dann werden Preisänderungen abgehört, sobald Echtzeitdienste geladen sind:

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

Den fertigen Code finden Sie unter src/main.ts.

Funktionsfähigkeit der App überprüfen

  1. Führen Sie npm run build aus, um die App neu zu erstellen.
  2. Öffnen Sie einen Browser-Tab für http://localhost:8080 oder aktualisieren Sie den vorhandenen Tab.

Bundle-Größe prüfen

  1. Öffnen Sie die Chrome-Entwicklertools.
  2. Wechseln Sie zum Tab Netzwerk.
  3. Seite aktualisieren, um Netzwerkanfragen zu erfassen
  4. Suchen Sie nach main.js und prüfen Sie die Größe.
  5. Jetzt sind es nur noch 115 KB (34,5 KB komprimiert). Das ist 75% kleiner als die ursprüngliche Bundle-Größe von 446 KB(138 KB komprimiert). Die Website lädt daher über 2 Sekunden schneller über eine 3G-Verbindung – eine enorme Verbesserung der Leistung und Nutzerfreundlichkeit.

9ea7398a8c8ef81b.png

8. Glückwunsch

Herzlichen Glückwunsch! Sie haben die App erfolgreich aktualisiert und sie kleiner und schneller gemacht.

Sie haben die Compat-Pakete verwendet, um die App nach und nach zu aktualisieren, und Firestore Lite, um das erste Seitenrendering zu beschleunigen. Anschließend haben Sie das Haupt-Firestore dynamisch geladen, um Preisänderungen zu streamen.

Außerdem haben Sie im Laufe dieses Codelabs die Bundle-Größe reduziert und die Ladezeit verbessert:

main.js

Ressourcengröße (KB)

Gezippte Größe (KB)

Ladezeit (Sekunden) (über langsames 3G)

v8

446

138

4,92

v9 compat

429

124

4.65

Modulare Authentifizierung nur in Version 9

348

102

4.2

V9 – vollständig modular

244

74,6

3.66

v9 – vollständig modular + Firestore Lite

117

34,9

2.88

32a71bd5a774e035.png

Sie kennen jetzt die wichtigsten Schritte, die für das Upgrade einer Web-App erforderlich sind, die das Firebase JS SDK v8 verwendet, damit das neue modulare JS SDK genutzt wird.

Weitere Informationen

Referenzdokumente