Optimieren Sie Ihre Web-App durch die Migration zum modularen Firebase JS SDK

1. Bevor Sie beginnen

Das modulare Firebase JS SDK ist eine Neufassung des bestehenden JS SDK und wird als nächste Hauptversion veröffentlicht. Es ermöglicht Entwicklern, ungenutzten Code aus dem Firebase JS SDK auszuschließ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 frei schwebenden Funktionen organisiert sind, die Sie importieren, und nicht in einem einzigen firebase Namespace, der alles enthält. Diese neue Art der Codeorganisation ermöglicht das Tree-Shaking, und Sie erfahren, wie Sie jede App, die derzeit das v8 Firebase JS SDK verwendet, auf das neue modulare aktualisieren.

Um einen reibungslosen Upgrade-Prozess zu gewährleisten, wird eine Reihe von Kompatibilitätspaketen bereitgestellt. In diesem Codelab erfahren Sie, wie Sie die Kompatibilitätspakete verwenden, um die App Stück für Stück zu portieren.

Was Sie bauen werden

In diesem Codelab migrieren Sie schrittweise eine vorhandene Aktien-Watchlist-Web-App, die das v8 JS SDK verwendet, in drei Schritten zum neuen modularen JS SDK:

  • Aktualisieren Sie die App, um die Kompatibilitätspakete zu verwenden
  • Rüsten Sie die App Stück für Stück von den Kompatibilitätspaketen auf die modulare API auf
  • Verwenden Sie Firestore Lite, eine einfache Implementierung des Firestore SDK, um die Leistung der App weiter zu verbessern

2d351cb47b604ad7.png

Dieses Codelab konzentriert sich auf die Aktualisierung des Firebase SDK. Andere Konzepte und Codeblöcke werden beschönigt und stehen Ihnen zum einfachen Kopieren und Einfügen zur Verfügung.

Was du brauchen wirst

  • Ein Browser Ihrer Wahl, z. B. Chrome
  • Der IDE/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 Erhalten des Codes finden Sie im nächsten Schritt des Codelabs.)

2. Machen Sie sich bereit

Holen Sie sich den Code

Alles, was Sie für dieses Projekt benötigen, befindet sich in einem Git-Repo. Um zu beginnen, müssen Sie sich den Code holen und ihn in Ihrer bevorzugten Entwicklungsumgebung öffnen.

Klonen Sie das Github-Repository des Codelab über die Befehlszeile:

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

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

Importieren Sie die App

  1. Öffnen oder importieren Sie mit Ihrer IDE das Verzeichnis codelab-modular-sdk .
  2. Führen Sie npm install , 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 , um den Webserver zu starten
  5. Öffnen Sie einen Browser-Tab zu http://localhost:8080

71a8a7d47392e8f4.png

3. Legen Sie eine Grundlinie fest

Was ist Ihr Ausgangspunkt?

Ihr Ausgangspunkt ist eine Aktien-Watchlist-App, die für dieses Codelab entwickelt wurde. Der Code wurde vereinfacht, um die Konzepte in diesem Codelab zu veranschaulichen, und er verfügt über wenig Fehlerbehandlung. Wenn Sie sich für die Wiederverwendung eines Teils dieses Codes in einer Produktionsanwendung entscheiden, stellen Sie sicher, dass Sie alle Fehler beheben und den gesamten Code vollständig testen.

Stellen Sie sicher, dass in der App alles funktioniert:

  1. Melden Sie sich anonym über den Login- Button oben rechts an.
  2. Suchen Sie nach dem Anmelden nach „NFLX“, „SBUX“ und „T“ und fügen Sie sie der Beobachtungsliste hinzu, indem Sie auf die Schaltfläche „ Hinzufügen “ klicken, die Buchstaben eingeben und auf die Suchergebniszeile klicken, die unten angezeigt wird.
  3. Entfernen Sie eine Aktie aus der Beobachtungsliste, indem Sie auf das x am Ende der Zeile klicken.
  4. Sehen Sie sich die Echtzeitaktualisierungen des Aktienkurses an.
  5. Öffnen Sie Chrome DevTools, gehen Sie zur Registerkarte „ Netzwerk “ und aktivieren Sie „Cache deaktivieren “ und „Große Anforderungszeilen verwenden“ . „Cache deaktivieren“ stellt sicher, dass wir nach einer Aktualisierung immer die neuesten Änderungen erhalten, und „Große Anforderungszeilen verwenden“ sorgt dafür, dass in der Zeile sowohl die übertragene Größe als auch die Ressourcengröße für eine Ressource angezeigt werden. In diesem Codelab interessiert uns hauptsächlich die Größe von main.js .

48a096debb2aa940.png

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

4397cb2c1327089.png

Steigen Sie jetzt ein und beginnen Sie mit der Migration der App auf die neue modulare API.

4. Verwenden Sie die Kompatibilitätspakete

Die Kompatibilitätspakete ermöglichen Ihnen ein Upgrade auf die neue SDK-Version, ohne den gesamten Firebase-Code auf einmal zu ändern. Sie können sie schrittweise auf die modulare API upgraden.

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

Am Ende jedes Schritts sollten Sie in der Lage sein, die App ohne Unterbrechung zu kompilieren und auszuführen und bei der Migration jedes Produkts eine Verringerung der Bundle-Größe festzustellen.

Holen Sie sich das neue SDK

Suchen Sie den Abschnitt „Abhängigkeiten“ in package.json und ersetzen Sie ihn durch Folgendes:

package.json

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

Installieren Sie die Abhängigkeiten neu

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

Importpfade ändern

Die Kompatibilitätspakete werden unter dem Submodul firebase/compat bereitgestellt, daher werden wir die Importpfade entsprechend aktualisieren:

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

src/firebase.ts

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

Überprüfen Sie, ob die App funktioniert

  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. Spielen Sie mit der App. Alles sollte noch funktionieren.

5. Aktualisieren Sie Auth, um die modulare API zu verwenden

Sie können Firebase-Produkte in beliebiger Reihenfolge aktualisieren. In diesem Codelab aktualisieren Sie zunächst Auth, um die grundlegenden Konzepte kennenzulernen, da die Auth-API relativ einfach ist. Das Upgrade von Firestore ist etwas aufwändiger, und Sie werden als Nächstes erfahren, wie das geht.

Aktualisieren Sie die Auth-Initialisierung

  1. Gehen Sie 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'.
  2. Ersetzen Sie export const firebaseAuth = app.auth(); mit:

src/firebase.ts

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

Auth-Code aktualisieren

  1. Gehen Sie zur Datei src/auth.ts
  2. Fügen Sie am Anfang 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'.
  2. Aktualisieren Sie die Funktionen, um die modulare API zu verwenden.

Wie Sie bereits gesehen haben, als wir die Importanweisung aktualisiert haben, sind Pakete in Version 9 um Funktionen organisiert, die Sie importieren können, im Gegensatz zu den APIs der Version 8, die auf einem punktierten Namespace- und Servicemuster basieren. Es ist diese neue Organisation des Codes, die das Tree-Shaking von ungenutztem Code ermöglicht, da Build-Tools dadurch 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 von getAuth() oder initializeAuth() zurückgegebene Objekt. Sie speichern den Status eines bestimmten Firebase-Dienstes und die Funktion verwendet den Status, um ihre Aufgaben auszuführen. Wenden wir 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';

Überprüfen Sie, ob die App funktioniert

  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. Spielen Sie mit der App. Alles sollte noch funktionieren.

Überprüfen Sie die Bündelgröße

  1. Öffnen Sie Chrome DevTools.
  2. Wechseln Sie zur Registerkarte Netzwerk .
  3. Aktualisieren Sie die Seite, um Netzwerkanfragen zu erfassen.
  4. Suchen Sie nach main.js und überprüfen Sie seine Größe. Sie haben die Bundle-Größe um 100 KB (36 KB gzipped) reduziert, also etwa 22 % kleiner, indem Sie nur ein paar Codezeilen geändert haben! Bei einer langsamen 3G-Verbindung lädt die Website außerdem 0,75 Sekunden schneller.

2e4eafaf66cd829b.png

6. Aktualisieren Sie Firebase App und Firestore, um die modulare API zu verwenden

Aktualisieren Sie die Firebase-Initialisierung

  1. Gehen Sie zur Datei src/firebase.ts.
  2. Ersetzen Sie import firebase from 'firebase/compat/app'; mit:

src/firebase.ts

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

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.appspot.com", 
    messagingSenderId: "875614679042", 
    appId: "1:875614679042:web:5813c3e70a33e91ba0371b"
});

Aktualisieren Sie die Firestore-Initialisierung

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

src/firebase.ts

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

src/firebase.ts

export const firestore = getFirestore();
  1. Entfernen Sie alle Zeilen nach „ export const firestore = ...

Importe aktualisieren

  1. Öffnen Sie die Datei src/services.ts.
  2. Entfernen Sie FirestoreFieldPath , FirestoreFieldValue und QuerySnapshot aus dem Import. Der Import aus './firebase' sollte nun wie folgt aussehen:

src/services.ts

import { firestore } from './firebase';
  1. Importieren Sie die Funktionen und Typen, die Sie verwenden möchten, oben in die Datei:
    **src/services.ts**
import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove, 
    onSnapshot, 
    query, 
    where, 
    documentId, 
    QuerySnapshot
} from 'firebase/firestore';
  1. Erstellen Sie einen Verweis auf die Sammlung, die alle Ticker 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 search() .

AddToWatchList() aktualisieren

Verwenden Sie doc() , um einen Dokumentverweis auf die Beobachtungsliste des Benutzers zu erstellen, und fügen Sie dann mit setDoc() mit arrayUnion() einen Ticker 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 });
}

deleteFromWatchList() aktualisieren

Entfernen Sie auf ähnliche Weise einen Ticker aus der Beobachtungsliste des Benutzers 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 });
}

SubscribeToTickerChanges() aktualisieren

  1. Verwenden Sie doc() , um zunächst einen Dokumentverweis auf die Watchlist des Benutzers zu erstellen, und überwachen Sie dann die Änderungen der Watchlist mit onSnapshot() :

src/services.ts

const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
   /* subscribe to ticker price changes */
});
  1. Sobald Sie die Ticker in der Beobachtungsliste haben, erstellen Sie mit query() eine Abfrage zum Abrufen ihrer Preise und verwenden Sie onSnapshot() , um ihre Preisänderungen abzuhören:

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

SubscribeToAllTickerChanges() aktualisieren

Zuerst verwenden Sie collection() , um einen Verweis auf die Sammlung zu erstellen, die zunächst die Preise für alle Ticker enthält, und verwenden dann onSnapshot() , um Preisänderungen abzuhören:

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

Überprüfen Sie, ob die App funktioniert

  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. Spielen Sie mit der App. Alles sollte noch funktionieren.

Überprüfen Sie die Bündelgröße

  1. Öffnen Sie Chrome DevTools.
  2. Wechseln Sie zur Registerkarte Netzwerk .
  3. Aktualisieren Sie die Seite, um Netzwerkanfragen zu erfassen.
  4. Suchen Sie nach main.js und überprüfen Sie seine Größe. Vergleichen Sie es noch einmal mit der ursprünglichen Bundle-Größe – wir haben die Bundle-Größe um über 200 KB (63,8 KB gzipped) oder 50 % kleiner reduziert, was einer um 1,3 Sekunden schnelleren Ladezeit entspricht!

7660cdc574ee8571.png

7. Verwenden Sie Firestore Lite, um das Rendern der ersten Seite zu beschleunigen

Was ist Firestore Lite?

Das Firestore SDK bietet komplexes Caching, Echtzeit-Streaming, dauerhaften Speicher, Offline-Synchronisierung mit mehreren Registerkarten, Wiederholungsversuche, optimistische Parallelität und vieles mehr und ist daher recht umfangreich. Möglicherweise möchten Sie die Daten jedoch nur einmal abrufen, ohne die erweiterten Funktionen zu benötigen. Für diese Fälle hat Firestore eine einfache und leichte Lösung entwickelt, ein brandneues Paket – Firestore Lite.

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

In diesem Schritt erfahren Sie, wie Sie mit Firestore Lite die Bundle-Größe reduzieren, um das Rendern der ersten Seite zu beschleunigen, und dann das Haupt-Firestore-SDK dynamisch laden, um Echtzeit-Updates zu abonnieren.

Sie werden den Code wie folgt umgestalten:

  1. Verschieben Sie Echtzeitdienste in eine separate Datei, damit sie mithilfe des dynamischen Imports dynamisch geladen werden können.
  2. Erstellen Sie neue Funktionen, um mit Firestore Lite Watchlist- und Aktienkurse abzurufen.
  3. Verwenden Sie die neuen Firestore Lite-Funktionen, um Daten abzurufen, um das erste Rendern der Seite durchzuführen, und laden Sie dann dynamisch die Echtzeitdienste, um Echtzeitaktualisierungen abzuhören.

Verschieben Sie Echtzeitdienste in eine neue Datei

  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 die erforderlichen Importe oben in der neuen Datei hinzu.

Hier müssen Sie noch ein paar Änderungen vornehmen:

  1. Erstellen Sie zunächst eine Firestore-Instanz aus dem Haupt-Firestore-SDK oben in der Datei, die in den Funktionen verwendet werden soll. Sie können die Firestore-Instanz hier nicht aus firebase.ts importieren, da Sie sie in wenigen Schritten in eine Firestore Lite-Instanz ändern werden, die nur für das anfängliche Rendern der Seite verwendet wird.
  2. Zweitens entfernen Sie die Variable firstload und den von ihr geschützten if-Block. Ihre Funktionalitäten 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);
   });
}

Verwenden Sie Firestore Lite, um Daten abzurufen

  1. Öffnen Sie src/services.ts.
  2. Ändern Sie den Importpfad von 'firebase/firestore' in '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 Rendern der Seite mit Firestore Lite benötigt werden:

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

Binde sie alle zusammen

  1. Öffnen Sie src/main.ts.
  2. Sie benötigen die neu erstellten Funktionen zum Abrufen von Daten für das anfängliche Rendern der Seite 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 mithilfe eines dynamischen Imports am Anfang der Datei. Die Variable loadRealtimeService ist ein Versprechen, das mit den Echtzeitdiensten aufgelöst wird, sobald der Code geladen ist. Sie werden es später verwenden, um Echtzeit-Updates zu abonnieren.

src/main.ts

const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
   setRealtimeServicesLoaded(true);
});
  1. Ändern Sie den Rückruf von onUserChange() in eine async Funktion, damit wir await im Funktionskörper 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() -Rückruf nach der if-Bedingung, bei der ein Benutzer angemeldet ist, und kopieren Sie den Code und fügen Sie ihn in die if-Anweisung ein:

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. Rufen Sie im else-Block, in dem kein Benutzer angemeldet ist, mit Firestore Lite Preisinformationen für alle Aktien ab, rendern Sie die Seite und hören Sie sich dann die Preisänderungen an, 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 in src/main.ts .

Überprüfen Sie, ob die App funktioniert

  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.

Überprüfen Sie die Bündelgröße

  1. Öffnen Sie Chrome Devtools.
  2. Wechseln Sie zur Registerkarte Netzwerk .
  3. Aktualisieren Sie die Seite, um Netzwerkanfragen zu erfassen
  4. Suchen Sie nach main.js und überprüfen Sie seine Größe.
  5. Jetzt sind es nur noch 115 KB (34,5 KB gzip). Das ist 75 % kleiner als die ursprüngliche Paketgröße von 446 KB (138 KB gzippt)! Dadurch wird die Website über eine 3G-Verbindung um mehr als 2 Sekunden schneller geladen – eine großartige Verbesserung der Leistung und des Benutzererlebnisses!

9ea7398a8c8ef81b.png

8. Herzlichen Glückwunsch

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

Sie haben die kompatiblen Pakete verwendet, um die App Stück für Stück zu aktualisieren, und Sie haben Firestore Lite verwendet, um das Rendern der ersten Seite zu beschleunigen, und dann den Haupt-Firestore dynamisch geladen, um Preisänderungen zu streamen.

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

main.js

Ressourcengröße (KB)

Gzip-Größe (KB)

Ladezeit (s) (über langsam 3g)

v8

446

138

4,92

v9 kompatibel

429

124

4,65

v9 nur modulare Auth

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 erforderlich sind, um eine Web-App, die v8 Firebase JS SDK verwendet, auf das neue modulare JS SDK zu aktualisieren.

Weiterführende Literatur

Referenzdokumente