Zwiększ możliwości swojej aplikacji internetowej, przechodząc na modułowy pakiet SDK Firebase JS

1. Zanim zaczniesz

Modułowy pakiet SDK Firebase JS to nowa wersja dotychczasowego pakietu SDK JS, która zostanie wydana jako kolejna wersja główna. Umożliwia to deweloperom wykluczanie nieużywanego kodu z pakietu Firebase JS SDK, aby tworzyć mniejsze pakiety i osiągać lepszą wydajność.

Najbardziej zauważalną różnicą w modułowym pakiecie SDK JS jest to, że funkcje są teraz zorganizowane w funkcje swobodne, które będziesz importować, a nie w jednym zakresie nazw firebase, który obejmuje wszystko. Ten nowy sposób organizacji kodu umożliwia usuwanie niepotrzebnych elementów z drzewa. Dowiesz się też, jak uaktualnić dowolną aplikację, która obecnie korzysta z wersji 8 pakietu Firebase JS SDK, do nowej wersji modułowej.

Aby zapewnić płynny proces uaktualniania, udostępniamy zestaw pakietów zgodności. Z tego ćwiczenia z programowania dowiesz się, jak używać pakietów zgodności do przenoszenia aplikacji etapami.

Co utworzysz

W tym laboratorium programistycznym przeprowadzisz w 3 etapach migrację istniejącej internetowej aplikacji do śledzenia akcji, która korzysta z pakietu SDK JS v8, na nowy modułowy pakiet SDK JS:

  • Zaktualizuj aplikację, aby używać pakietów zgodności.
  • stopniowo przekształcać aplikację z pakietów zgodności na interfejs API w wersji modułowej.
  • Użyj Firestore Lite, czyli lekkiej implementacji pakietu SDK Firestore, aby jeszcze bardziej zwiększyć wydajność aplikacji.

2d351cb47b604ad7.png

Ten warsztat dotyczy uaktualniania pakietu SDK Firebase. Inne koncepcje i bloki kodu zostały zamaskowane. Można je po prostu skopiować i wkleić.

Czego potrzebujesz

  • przeglądarkę, np. Chrome;
  • Wybrany edytor kodu lub tekstowy, np. WebStorm, Atom, Sublime lub VS Code.
  • Menedżer pakietów npm, który jest zwykle dostarczany z Node.js.
  • przykładowy kod z codelab (jak go pobrać, dowiesz się z następnego kroku w codelab);

2. Konfiguracja

Pobierz kod

Wszystko, czego potrzebujesz do tego projektu, znajduje się w repozytorium Git. Aby rozpocząć, pobierz kod i otwórz go w ulubionym środowisku programistycznym.

Sklonuj repozytorium GitHub z codelab z poziomu wiersza poleceń:

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

Jeśli nie masz zainstalowanego git, możesz pobrać repozytorium jako plik ZIP i rozpakować pobrany plik ZIP.

Importowanie aplikacji

  1. Za pomocą środowiska IDE otwórz lub zaimportuj katalog codelab-modular-sdk.
  2. Uruchom npm install, aby zainstalować zależności wymagane do kompilacji i lokalnego uruchamiania aplikacji.
  3. Uruchom npm run build, aby skompilować aplikację.
  4. Uruchom npm run serve, aby uruchomić serwer WWW
  5. Otwórz kartę przeglądarki na stronie http://localhost:8080.

71a8a7d47392e8f4.png

3. Ustal wartość odniesienia

Jaki jest Twój punkt wyjścia?

Punktem wyjścia jest aplikacja z listą obserwowanych akcji zaprojektowana na potrzeby tego ćwiczenia. Kod został uproszczony, aby zilustrować pojęcia w tym ćwiczeniu, i nie zawiera wielu elementów obsługi błędów. Jeśli zdecydujesz się użyć tego kodu w aplikacji produkcyjnej, pamiętaj, aby obsłużyć wszystkie błędy i przejrzeć cały kod.

Sprawdź, czy wszystko działa w aplikacji:

  1. Zaloguj się anonimowo, klikając przycisk logowania w prawym górnym rogu.
  2. Po zalogowaniu się wyszukaj i dodaj „NFLX”, „SBUX” i „T” do listy obserwowanych, klikając przycisk Dodaj, wpisując litery i klikając wiersz wyników wyszukiwania, który pojawi się poniżej.
  3. Aby usunąć akcje z listy obserwowanych, kliknij x na końcu wiersza.
  4. Obserwuj bieżące zmiany ceny akcji.
  5. Otwórz Narzędzia deweloperskie w Chrome, otwórz kartę Sieć i odznacz opcje Wyłącz pamięć podręczną oraz Używaj dużych wierszy żądań. Opcja Wyłącz pamięć podręczną sprawia, że po odświeżeniu zawsze otrzymujemy najnowsze zmiany, a opcja Użyj dużych wierszy żądań sprawia, że wiersz wyświetla zarówno rozmiar przesłanych danych, jak i rozmiar zasobu. W tym Codelab interesuje nas głównie rozmiar main.js.

48a096debb2aa940.png

  1. Załaduj aplikację w różnych warunkach sieciowych, symulując ograniczanie. W tym ćwiczeniu będziesz używać wolnego 3G do pomiaru czasu wczytywania, ponieważ w takich warunkach mniejszy rozmiar pakietu jest najbardziej przydatny.

4397cb2c1327089.png

Teraz zacznij migrować aplikację do nowego modułowego interfejsu API.

4. Korzystanie z pakietów wymagających dostosowania

Pakiety zgodności umożliwiają przejście na nową wersję pakietu SDK bez jednoczesnej zmiany całego kodu Firebase. Możesz stopniowo przenosić je na modułowe API.

W tym kroku uaktualnisz bibliotekę Firebase z wersji 8 na nową i zmienisz kod, aby używać pakietów zgodności. Z tych kroków dowiesz się, jak najpierw uaktualnić tylko kod uwierzytelniania Firebase, aby używać modułowego interfejsu API, a potem uaktualnić kod Firestore.

Po zakończeniu każdego kroku powinnaś/powinieneś mieć możliwość skompilowania i uruchomienia aplikacji bez błędów. W miarę migracji poszczególnych usług powinieneś/powinnaś też zauważyć zmniejszenie rozmiaru pakietu.

Pobierz nowy pakiet SDK

Znajdź sekcję zależności w pliku package.json i zastąp ją tym fragmentem kodu:

package.json

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

Ponowne instalowanie zależności

Zmieniliśmy wersję zależności, więc musimy ponownie uruchomić npm install, aby uzyskać nową wersję zależności.

Zmiana ścieżek importu

Pakiety zgodności są dostępne w ramach podmodułu firebase/compat, więc zaktualizujemy ścieżki importu:

  1. Otwórz plik src/firebase.ts
  2. Zastąp dotychczasowe importy tymi:

src/firebase.ts

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

Sprawdzanie, czy aplikacja działa prawidłowo

  1. Uruchom npm run build, aby ponownie utworzyć aplikację.
  2. Otwórz kartę przeglądarki http://localhost:8080 lub odśwież obecną kartę.
  3. Pobaw się aplikacją. Wszystko powinno działać.

5. Uaktualnianie Auth do wersji korzystającej z modułowego interfejsu API

Usługi Firebase możesz przekształcać w dowolnej kolejności. W tym ćwiczeniu najpierw uaktualnisz interfejs Auth, aby poznać podstawowe pojęcia, ponieważ interfejs Auth API jest stosunkowo prosty. Uaktualnianie Firestore jest nieco bardziej skomplikowane, ale w następnym kroku dowiesz się, jak to zrobić.

Inicjowanie uwierzytelniania aktualizacji

  1. Otwórz plik src/firebase.ts
  2. Dodaj ten import:

src/firebase.ts

import { initializeAuth, indexedDBLocalPersistence } from 'firebase/auth';
  1. Usuń: import ‘firebase/compat/auth'.
  2. Zastąp export const firebaseAuth = app.auth();:

src/firebase.ts

export const firebaseAuth = initializeAuth(app, { persistence: [indexedDBLocalPersistence] });
  1. Usuń export type User = firebase.User; na końcu pliku. User zostanie wyeksportowany bezpośrednio do pliku src/auth.ts, który zmienisz w następnym kroku.

Zaktualizuj kod autoryzacji

  1. Otwórz plik src/auth.ts
  2. Dodaj do góry pliku te instrukcje importu:

src/auth.ts

import { 
    signInAnonymously, 
    signOut,
    onAuthStateChanged,
    User
} from 'firebase/auth';
  1. Usuń User z import { firebaseAuth, User } from './firebase';, ponieważ User zostało już zaimportowane z ‘firebase/auth'.
  2. Zaktualizuj funkcje, aby używać modułowego interfejsu API.

Jak już widzisz, gdy aktualizowaliśmy instrukcję importowania, pakiety w wersji 9 są zorganizowane wokół funkcji, które możesz importować, w przeciwieństwie do interfejsów API w wersji 8, które są oparte na łańcuchu nazw domeny i wzorze usługi. To nowe uporządkowanie kodu umożliwia usuwanie nieużywanego kodu z drzewa, ponieważ pozwala narzędziom do kompilacji analizować, który kod jest używany, a który nie.

W wersji 9 usługi są przekazywane jako pierwszy argument funkcji. Usługi to obiekty, które otrzymujesz po zainicjowaniu usługi Firebase, np. obiekt zwrócony przez funkcję getAuth() lub initializeAuth(). Zawierają one stan konkretnej usługi Firebase, a funkcja korzysta z tego stanu do wykonywania swoich zadań. Zastosujmy ten wzór do implementacji tych funkcji:

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

Sprawdzanie działania aplikacji

  1. Uruchom npm run build, aby ponownie utworzyć aplikację.
  2. Otwórz kartę przeglądarki z adresem http://localhost:8080 lub odśwież obecną kartę.
  3. Pobaw się aplikacją. Wszystko powinno działać.

Sprawdzanie rozmiaru pakietu

  1. Otwórz Narzędzia deweloperskie w Chrome.
  2. Przejdź na kartę Sieć.
  3. Odśwież stronę, aby przechwycić żądania sieciowe.
  4. Odszukaj plik main.js i sprawdź jego rozmiar. Rozmiar pakietu zmniejszył się o 100 KB (36 KB w formacie skompresowanym) lub o około 22%, ponieważ zmieniono tylko kilka linii kodu. Strona wczytuje się też o 0,75 s szybciej przy wolniejszym połączeniu 3G.

2e4eafaf66cd829b.png

6. Uaktualnianie Firebase App i Firestore do korzystania z modułowego interfejsu API

Aktualizowanie inicjalizacji Firebase

  1. Otwórz plik src/firebase.ts.
  2. Zastąp import firebase from ‘firebase/compat/app';:

src/firebase.ts

import { initializeApp } from 'firebase/app';
  1. Zastąp 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"
});

Aktualizowanie inicjalizacji Firestore

  1. W tym samym pliku src/firebase.ts, zastąp import 'firebase/compat/firestore'; wartością

src/firebase.ts

import { getFirestore } from 'firebase/firestore';
  1. Zastąp export const firestore = app.firestore();:

src/firebase.ts

export const firestore = getFirestore();
  1. Usuń wszystkie wiersze po „export const firestore = ...

Aktualizowanie importów

  1. Otwórz plik src/services.ts.
  2. Usuń z importu wartości FirestoreFieldPath, FirestoreFieldValueQuerySnapshot. Import z './firebase' powinien wyglądać tak:

src/services.ts

import { firestore } from './firebase';
  1. U góry pliku zaimportuj funkcje i typy, których będziesz używać:
    **src/services.ts**
import { 
    collection, 
    getDocs, 
    doc, 
    setDoc, 
    arrayUnion, 
    arrayRemove, 
    onSnapshot, 
    query, 
    where, 
    documentId, 
    QuerySnapshot
} from 'firebase/firestore';
  1. Utwórz odwołanie do kolekcji zawierającej wszystkie tickery:

src/services.ts

const tickersCollRef = collection(firestore, 'current');
  1. Aby pobrać wszystkie dokumenty z kolekcji, użyj elementu getDocs():

src/services.ts

const tickers = await getDocs(tickersCollRef);

Pełny kod znajdziesz na stronie search().

Zaktualizuj funkcję addToWatchList()

Użyj elementu doc(), aby utworzyć odwołanie do dokumentu na liście obserwowanych, a następnie dodaj do niego ticker za pomocą elementu setDoc() z elementem 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 });
}

Zaktualizuj deleteFromWatchList()

Podobnie możesz usunąć ticker z listy Do obejrzenia użytkownika, używając setDoc() z 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 });
}

Zaktualizuj subscribeToTickerChanges()

  1. Najpierw użyj doc(), aby utworzyć odwołanie do dokumentu na liście obserwowanych, a potem odsłuchaj zmiany na liście za pomocą onSnapshot():

src/services.ts

const watchlistRef = doc(firestore, `watchlist/${user.uid}`);
const unsubscribe = onSnapshot(watchlistRef, snapshot => {
   /* subscribe to ticker price changes */
});
  1. Gdy masz już tickery na liście obserwowanych, użyj zapytania query(), aby pobrać ich ceny, i zapytania onSnapshot(), aby śledzić zmiany ich cen:

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

Pełną implementację znajdziesz w funkcji subscribeToTickerChanges().

Zaktualizuj subscribeToAllTickerChanges()

Najpierw użyjesz funkcji collection(), aby utworzyć odwołanie do kolekcji zawierającej ceny wszystkich tickerów, a potem użyjesz funkcji onSnapshot(), aby słuchać zmian cen:

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

Sprawdzanie, czy aplikacja działa

  1. Uruchom npm run build, aby ponownie utworzyć aplikację.
  2. Otwórz kartę przeglądarki z adresem http://localhost:8080 lub odśwież obecną kartę.
  3. Pobaw się aplikacją. Wszystko powinno działać.

Sprawdzanie rozmiaru pakietu

  1. Otwórz Narzędzia deweloperskie w Chrome.
  2. Przejdź na kartę Sieć.
  3. Odśwież stronę, aby przechwycić żądania sieciowe.
  4. Poszukaj main.js i sprawdź jego rozmiar. Porównaj to z pierwotnym rozmiarem pakietu – zmniejszyliśmy go o ponad 200 KB (63,8 KB w formacie skompresowanym) lub o 50%, co przekłada się na skrócenie czasu wczytywania o 1,3 s.

7660cdc574ee8571.png

7. Używanie Firestore Lite do przyspieszania początkowego renderowania strony

Co to jest Firestore Lite?

Pakiet SDK Firestore oferuje złożone buforowanie, przesyłanie strumieniowe w czasie rzeczywistym, trwałe przechowywanie, synchronizację offline na wielu kartach, próby ponownego połączenia, optymistyczną współbieżność i wiele innych funkcji, dlatego jego rozmiar jest dość duży. Możesz jednak po prostu chcieć pobrać dane tylko raz, bez korzystania z funkcji zaawansowanych. W takich przypadkach Firestore oferuje proste i lekkie rozwiązanie, czyli zupełnie nowy pakiet – Firestore Lite.

Jednym z przydatnych zastosowań Firestore Lite jest optymalizacja wydajności początkowego renderowania strony, w której przypadku wystarczy wiedzieć, czy użytkownik jest zalogowany, a potem odczytać dane z Firestore, aby je wyświetlić.

W tym kroku dowiesz się, jak użyć Firestore lite, aby zmniejszyć rozmiar pakietu i przyspieszyć początkowe renderowanie strony, a potem wczytać główny pakiet SDK Firestore dynamicznie, aby subskrybować aktualizacje w czasie rzeczywistym.

Przepisz kod, aby:

  1. Przenoszenie usług w czasie rzeczywistym do osobnego pliku, aby można je było wczytywać dynamicznie za pomocą importu dynamicznego.
  2. Utwórz nowe funkcje, aby używać Firestore Lite do pobierania cen akcji i list obserwowanych.
  3. Użyj nowych funkcji Firestore Lite, aby pobrać dane potrzebne do początkowego renderowania strony, a potem dynamicznie wczytaj usługi w czasie rzeczywistym, aby odbierać aktualizacje w czasie rzeczywistym.

Przenoszenie usług w czasie rzeczywistym do nowego pliku

  1. Utwórz nowy plik o nazwie src/services.realtime.ts..
  2. Przenieś funkcje subscribeToTickerChanges()subscribeToAllTickerChanges() z pliku src/services.ts do nowego pliku.
  3. Dodaj niezbędne importy na początku nowego pliku.

Musisz jeszcze wprowadzić kilka zmian:

  1. Najpierw utwórz instancję Firestore z głównego pakietu SDK Firestore u góry pliku, aby można było jej używać w funkcjach. Nie możesz tu zaimportować instancji Firestore z firebase.ts, ponieważ w kilku krokach zmienisz ją na instancję Firestore Lite, która będzie używana tylko do początkowego renderowania strony.
  2. Po drugie, pozbądź się zmiennej firstload i zabezpieczonego przez nią bloku if. Ich funkcje zostaną przeniesione do nowych funkcji, które utworzysz w następnym kroku.

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

Pobieranie danych z Firestore lite

  1. Otwórz: src/services.ts.
  2. Zmień ścieżkę importu z ‘firebase/firestore' na ‘firebase/firestore/lite',, dodaj getDoc i usuń onSnapshot z listy importu:

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. Dodaj funkcje służące do pobierania danych potrzebnych do początkowego renderowania strony za pomocą 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. Otwórz plik src/firebase.ts i zmień ścieżkę importu z ‘firebase/firestore' na ‘firebase/firestore/lite':.

src/firebase.ts

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

Połącz wszystkie elementy

  1. Otwórz: src/main.ts.
  2. Nowo utworzone funkcje będą potrzebne do pobierania danych na potrzeby początkowego renderowania strony, a kilka funkcji pomocniczych do zarządzania stanem aplikacji. Zaktualizuj teraz importy:

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. Załaduj src/services.realtime za pomocą importu dynamicznego u góry pliku. Zmienna loadRealtimeService to obietnica, która zostanie rozwiązana przez usługi w czasie rzeczywistym po załadowaniu kodu. Użyjesz go później, aby subskrybować aktualizacje w czasie rzeczywistym.

src/main.ts

const loadRealtimeService = import('./services.realtime');
loadRealtimeService.then(() => {
   setRealtimeServicesLoaded(true);
});
  1. Zmień funkcję onUserChange() na funkcję async, aby móc używać w jej treści funkcji await:

src/main.ts

onUserChange(async user => {
 // callback body
});
  1. Teraz pobierz dane, aby dokonać początkowego renderowania strony za pomocą nowych funkcji utworzonych w poprzednim kroku.

W funkcji zwracającej onUserChange() odszukaj warunek if, w którym użytkownik jest zalogowany, a potem skopiuj i wklej kod w oświadczeniu 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. W bloku else, w którym żaden użytkownik nie jest zalogowany, pobierz informacje o cenach wszystkich produktów za pomocą Firestore Lite, wyrenderuj stronę, a potem nasłuchuj zmian cen po załadowaniu usług w czasie rzeczywistym:

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

Gotowy kod znajdziesz w pliku src/main.ts.

Sprawdzanie, czy aplikacja działa

  1. Uruchom npm run build, aby ponownie utworzyć aplikację.
  2. Otwórz kartę przeglądarki http://localhost:8080 lub odśwież obecną kartę.

Sprawdzanie rozmiaru pakietu

  1. Otwórz Narzędzia deweloperskie w Chrome.
  2. Przejdź na kartę Sieć.
  3. Odśwież stronę, aby przechwycić żądania sieciowe
  4. Poszukaj main.js i sprawdź jego rozmiar.
  5. Teraz ma on tylko 115 KB (34,5 KB po skompresowaniu). To o 75% mniej niż rozmiar oryginalnego pakietu, który wynosił 446 KB(138 KB po skompresowaniu). W efekcie witryna wczytuje się o ponad 2 sekundy szybciej w przypadku połączenia 3G – to świetna wydajność i wygoda dla użytkowników.

9ea7398a8c8ef81b.png

8. Gratulacje

Gratulacje! Udało Ci się uaktualnić aplikację, zmniejszyć jej rozmiar i przyspieszyć jej działanie.

Używasz pakietów zgodności do stopniowego ulepszania aplikacji i Firestore Lite do przyspieszania początkowego renderowania strony, a potem wczytujesz dynamicznie główną bazę danych Firestore, aby przesyłać zmiany cen.

W ramach tego ćwiczenia udało Ci się też zmniejszyć rozmiar pakietu i skrócić czas jego wczytywania:

main.js

rozmiar zasobu (KB)

rozmiar skompresowany (KB)

Czas wczytywania (s) (połączenie 3G o niskiej szybkości)

v8

446

138

4,92

v9 zgodny

429

124

4,65

tylko w Auth modułowym w wersji 9

348

102

4.2

v9 w pełni modułowej

244

74,6

3,66

v9 w wersji całkowicie modułowej + Firestore lite

117

34,9

2,88

32a71bd5a774e035.png

Znasz już najważniejsze kroki wymagane do uaktualnienia aplikacji internetowej, która korzysta z pakietu Firebase JS SDK w wersji 8, tak aby używała nowego modułowego pakietu JS SDK.

Więcej informacji

Dokumenty referencyjne