Integrieren Sie Firebase mit einer Next.js-App

1. Bevor Sie beginnen

In diesem Codelab erfahren Sie, wie Sie Firebase in eine Next.js-Web-App namens Friendly Eats integrieren, eine Website für Restaurantbewertungen.

Friendly Eats-Web-App

Die fertige Web-App bietet nützliche Funktionen, die zeigen, wie Firebase Sie beim Erstellen von Next.js-Apps unterstützen kann. Zu diesen Funktionen gehören die folgenden:

  • Mit Google anmelden und abmelden: Mit der fertigen Web-App können Sie sich mit Google anmelden und abmelden. Benutzeranmeldung und -persistenz werden vollständig über die Firebase-Authentifizierung verwaltet.
  • Bilder: Mit der fertigen Web-App können angemeldete Benutzer Restaurantbilder hochladen. Bildressourcen werden in Cloud Storage für Firebase gespeichert. Das Firebase JavaScript SDK stellt eine öffentliche URL für hochgeladene Bilder bereit. Diese öffentliche URL wird dann im entsprechenden Restaurantdokument im Cloud Firestore gespeichert.
  • Bewertungen: Mit der fertigen Web-App können angemeldete Benutzer Bewertungen von Restaurants veröffentlichen, die aus einer Sternebewertung und einer Textnachricht bestehen. Bewertungsinformationen werden im Cloud Firestore gespeichert.
  • Filter: Mit der fertigen Web-App können angemeldete Benutzer die Liste der Restaurants nach Kategorie, Standort und Preis filtern. Sie können auch die verwendete Sortiermethode anpassen. Der Zugriff auf Daten erfolgt über Cloud Firestore und Firestore-Abfragen werden basierend auf den verwendeten Filtern angewendet.

Voraussetzungen

  • Kenntnisse in Next.js und JavaScript

Was Sie lernen werden

  • So verwenden Sie Firebase mit dem Next.js App Router und serverseitigem Rendering.
  • So behalten Sie Bilder in Cloud Storage für Firebase bei.
  • So lesen und schreiben Sie Daten in einer Cloud Firestore-Datenbank.
  • So verwenden Sie die Anmeldung bei Google mit dem Firebase JavaScript SDK.

Was du brauchen wirst

  • Git
  • Das Java Development Kit
  • Eine aktuelle stabile Version von Node.js
  • Ein Browser Ihrer Wahl, z. B. Google Chrome
  • Eine Entwicklungsumgebung mit Code-Editor und Terminal
  • Ein Google-Konto für die Erstellung und Verwaltung Ihres Firebase-Projekts
  • Die Möglichkeit, Ihr Firebase-Projekt auf den Blaze-Preisplan zu aktualisieren

2. Richten Sie Ihre Entwicklungsumgebung ein

Dieses Codelab stellt die Starter-Codebasis der App bereit und basiert auf der Firebase-CLI.

Laden Sie das Repository herunter

  1. Klonen Sie in Ihrem Terminal das GitHub-Repository des Codelab:
    git clone https://github.com/firebase/friendlyeats-web.git
    
  2. Das GitHub-Repository enthält Beispielprojekte für mehrere Plattformen. Dieses Codelab verwendet jedoch nur das Verzeichnis nextjs-start . Beachten Sie die folgenden Verzeichnisse:
    • nextjs-start : enthält den Startercode, auf dem Sie aufbauen.
    • nextjs-end : enthält den Lösungscode für die fertige Web-App.
  3. Navigieren Sie in Ihrem Terminal zum Verzeichnis nextjs-start und installieren Sie die erforderlichen Abhängigkeiten:
    cd friendlyeats-web/nextjs-start
    npm install
    

Installieren oder aktualisieren Sie die Firebase-CLI

Führen Sie den folgenden Befehl aus, um zu überprüfen, ob Sie die Firebase-CLI installiert haben und dass es sich um Version 12.5.4 oder höher handelt:

firebase --version
  • Wenn Sie die Firebase-CLI installiert haben, diese jedoch nicht Version 12.5.4 oder höher ist, aktualisieren Sie sie:
    npm update -g firebase-tools
    
  • Wenn Sie die Firebase-CLI nicht installiert haben, installieren Sie sie:
    npm install -g firebase-tools
    

Wenn Sie die Firebase-CLI aufgrund von Berechtigungsfehlern nicht installieren können, lesen Sie die npm-Dokumentation oder verwenden Sie eine andere Installationsoption .

Melden Sie sich bei Firebase an

  1. Führen Sie den folgenden Befehl aus, um sich bei der Firebase-CLI anzumelden:
    firebase login
    
  2. Je nachdem, ob Firebase Daten sammeln soll, geben Sie Y oder N ein.
  3. Wählen Sie in Ihrem Browser Ihr Google-Konto aus und klicken Sie dann auf Zulassen .

3. Richten Sie Ihr Firebase-Projekt ein

In diesem Abschnitt richten Sie ein Firebase-Projekt ein und verknüpfen damit eine Firebase-Web-App. Außerdem richten Sie die Firebase-Dienste ein, die von der Beispiel-Web-App verwendet werden.

Erstellen Sie ein Firebase-Projekt

  1. Klicken Sie in der Firebase-Konsole auf Projekt erstellen .
  2. Geben Sie im Textfeld „Geben Sie Ihren Projektnamen ein FriendlyEats Codelab (oder einen Projektnamen Ihrer Wahl) ein und klicken Sie dann auf „Weiter“ .
  3. Für dieses Codelab benötigen Sie Google Analytics nicht. Deaktivieren Sie daher die Option „Google Analytics für dieses Projekt aktivieren“ .
  4. Klicken Sie auf Projekt erstellen .
  5. Warten Sie, bis Ihr Projekt bereitgestellt ist, und klicken Sie dann auf Weiter .
  6. Gehen Sie in Ihrem Firebase-Projekt zu Projekteinstellungen . Notieren Sie sich Ihre Projekt-ID, da Sie diese später benötigen. Mit dieser eindeutigen Kennung wird Ihr Projekt identifiziert (z. B. in der Firebase-CLI).

Fügen Sie Ihrem Firebase-Projekt eine Web-App hinzu

  1. Navigieren Sie in Ihrem Firebase-Projekt zu Ihrer Projektübersicht und klicken Sie dann auf e41f2efdd9539c31.png Netz .
  2. Geben Sie im Textfeld „App-Spitzname“ einen einprägsamen App-Spitznamen ein, z. B. My Next.js app .
  3. Aktivieren Sie das Kontrollkästchen „Auch Firebase Hosting für diese App einrichten“ .
  4. Klicken Sie auf App registrieren > Weiter > Weiter > Weiter zur Konsole .

Aktualisieren Sie Ihren Firebase-Preisplan

Um Web-Frameworks verwenden zu können, muss Ihr Firebase-Projekt im Blaze-Preisplan enthalten sein, was bedeutet, dass es mit einem Cloud-Rechnungskonto verknüpft ist.

  • Für ein Cloud-Rechnungskonto ist eine Zahlungsmethode erforderlich, beispielsweise eine Kreditkarte.
  • Wenn Sie neu bei Firebase und Google Cloud sind, prüfen Sie, ob Sie Anspruch auf ein Guthaben von 300 $ und ein Cloud-Rechnungskonto für eine kostenlose Testversion haben.

Beachten Sie jedoch, dass für die Fertigstellung dieses Codelabs keine tatsächlichen Kosten anfallen sollten.

Um Ihr Projekt auf den Blaze-Plan zu aktualisieren, führen Sie die folgenden Schritte aus:

  1. Wählen Sie in der Firebase-Konsole die Option „Upgrade Ihres Plans“ aus.
  2. Wählen Sie im Dialogfeld den Blaze-Plan aus und befolgen Sie dann die Anweisungen auf dem Bildschirm, um Ihr Projekt einem Cloud-Rechnungskonto zuzuordnen.
    Wenn Sie ein Cloud-Rechnungskonto erstellen mussten, müssen Sie möglicherweise zum Upgrade-Ablauf in der Firebase-Konsole zurücknavigieren, um das Upgrade abzuschließen.

Richten Sie Firebase-Dienste in der Firebase-Konsole ein

Authentifizierung einrichten

  1. Navigieren Sie in der Firebase-Konsole zu Authentication .
  2. Klicken Sie auf „Erste Schritte“ .
  3. Klicken Sie in der Spalte „Zusätzliche Anbieter“ auf Google > Aktivieren .
  4. Geben Sie im Textfeld „Öffentlicher Name für Projekt“ einen einprägsamen Namen ein, z. B. My Next.js app .
  5. Wählen Sie im Dropdown-Menü „Support-E-Mail für Projekt“ Ihre E-Mail-Adresse aus.
  6. Klicken Sie auf Speichern .

Richten Sie Cloud Firestore ein

  1. Navigieren Sie in der Firebase-Konsole zu Firestore .
  2. Klicken Sie auf Datenbank erstellen > Im Testmodus starten > Weiter .
    Später in diesem Codelab fügen Sie Sicherheitsregeln hinzu, um Ihre Daten zu schützen. Verteilen oder machen Sie eine App nicht öffentlich verfügbar, ohne Sicherheitsregeln für Ihre Datenbank hinzuzufügen.
  3. Verwenden Sie den Standardstandort oder wählen Sie einen Standort Ihrer Wahl.
    Für eine echte App möchten Sie einen Standort auswählen, der sich in der Nähe Ihrer Benutzer befindet. Beachten Sie, dass dieser Speicherort später nicht geändert werden kann und automatisch auch der Speicherort Ihres Standard-Cloud-Storage-Buckets ist (nächster Schritt).
  4. Klicken Sie auf Fertig .

Richten Sie Cloud Storage für Firebase ein

  1. Navigieren Sie in der Firebase-Konsole zu Storage .
  2. Klicken Sie auf Erste Schritte > Im Testmodus starten > Weiter .
    Später in diesem Codelab fügen Sie Sicherheitsregeln hinzu, um Ihre Daten zu schützen. Verteilen oder machen Sie eine App nicht öffentlich verfügbar, ohne Sicherheitsregeln für Ihren Speicher-Bucket hinzuzufügen.
  3. Der Standort Ihres Buckets sollte bereits ausgewählt sein (da Sie Firestore im vorherigen Schritt eingerichtet haben).
  4. Klicken Sie auf Fertig .

4. Überprüfen Sie die Starter-Codebasis

In diesem Abschnitt überprüfen Sie einige Bereiche der Starter-Codebasis der App, zu denen Sie in diesem Codelab Funktionen hinzufügen.

Ordner- und Dateistruktur

Die folgende Tabelle enthält eine Übersicht über die Ordner- und Dateistruktur der App:

Ordner und Dateien

Beschreibung

src/components

React-Komponenten für Filter, Header, Restaurantdetails und Bewertungen

src/lib

Hilfsfunktionen, die nicht unbedingt an React oder Next.js gebunden sind

src/lib/firebase

Firebase-spezifischer Code und Firebase-Konfiguration

public

Statische Assets in der Web-App, z. B. Symbole

src/app

Routing mit dem Next.js App Router

src/app/restaurant

Ein API-Routenhandler

package.json und package-lock.json

Projektabhängigkeiten mit npm

next.config.js

Next.js-spezifische Konfiguration (Serveraktionen sind aktiviert )

jsconfig.json

Konfiguration des JavaScript-Sprachdienstes

Server- und Client-Komponenten

Die App ist eine Next.js-Web-App, die den App Router verwendet. In der gesamten App wird Server-Rendering verwendet. Beispielsweise ist die Datei src/app/page.js eine Serverkomponente, die für die Hauptseite verantwortlich ist. Die Datei src/components/RestaurantListings.jsx ist eine Client-Komponente, die durch die Anweisung "use client" am Anfang der Datei gekennzeichnet ist.

Anweisungen importieren

Möglicherweise bemerken Sie Importanweisungen wie die folgenden:

import RatingPicker from "@/src/components/RatingPicker.jsx";

Die App verwendet das @ -Symbol, um umständliche relative Importpfade zu vermeiden, und wird durch Pfadaliase ermöglicht.

Firebase-spezifische APIs

Der gesamte Firebase-API-Code ist im Verzeichnis src/lib/firebase eingeschlossen. Einzelne React-Komponenten importieren dann die umschlossenen Funktionen aus dem Verzeichnis src/lib/firebase , anstatt Firebase-Funktionen direkt zu importieren.

Scheindaten

Scheinrestaurant- und Bewertungsdaten sind in der Datei src/lib/randomData.js enthalten. Daten aus dieser Datei werden im Code in der Datei src/lib/fakeRestaurants.js zusammengestellt.

5. Richten Sie lokales Hosting mit dem Firebase Hosting-Emulator ein

In diesem Abschnitt verwenden Sie den Firebase Hosting-Emulator , um die Next.js-Webanwendung lokal auszuführen.

Am Ende dieses Abschnitts führt der Firebase Hosting-Emulator die Next.js-App für Sie aus, sodass Sie Next.js nicht in einem separaten Prozess als die Emulatoren ausführen müssen.

Laden Sie ein Firebase-Dienstkonto herunter und verwenden Sie es

Die Web-App, die Sie in diesem Codelab erstellen, verwendet serverseitiges Rendering mit Next.js .

Das Firebase Admin SDK für Node.js wird verwendet, um sicherzustellen, dass Sicherheitsregeln vom serverseitigen Code aus funktionieren. Um APIs in Firebase Admin zu verwenden, müssen Sie ein Firebase- Dienstkonto von der Firebase-Konsole herunterladen und verwenden.

  1. Navigieren Sie in der Firebase-Konsole zur Seite „Dienstkonten“ in Ihren Projekteinstellungen .
  2. Klicken Sie auf Neuen privaten Schlüssel generieren > Schlüssel generieren .
  3. Nachdem die Datei in Ihr Dateisystem heruntergeladen wurde, ermitteln Sie den vollständigen Pfad zu dieser Datei.
    Wenn Sie die Datei beispielsweise in Ihr Download- Verzeichnis heruntergeladen haben, könnte der vollständige Pfad so aussehen: /Users/me/Downloads/my-project-id-firebase-adminsdk-123.json
  4. Legen Sie in Ihrem Terminal die Umgebungsvariable GOOGLE_APPLICATION_CREDENTIALS auf den Pfad Ihres heruntergeladenen privaten Schlüssels fest. In einer Unix-Umgebung könnte der Befehl so aussehen:
    export GOOGLE_APPLICATION_CREDENTIALS="/Users/me/Downloads/my-project-id-firebase-adminsdk-123.json"
    
  5. Lassen Sie dieses Terminal geöffnet und verwenden Sie es für den Rest dieses Codelabs, da Ihre Umgebungsvariable möglicherweise verloren geht, wenn Sie eine neue Terminalsitzung starten.
    Wenn Sie eine neue Terminalsitzung öffnen, müssen Sie den vorherigen Befehl erneut ausführen.

Fügen Sie Ihre Firebase-Konfiguration zu Ihrem Web-App-Code hinzu

  1. Navigieren Sie in der Firebase-Konsole zu Ihren Projekteinstellungen .
  2. Suchen Sie im SDK-Setup- und Konfigurationsbereich nach der Variable firebaseConfig und kopieren Sie ihre Eigenschaften und deren Werte.
  3. Öffnen Sie die .env Datei in Ihrem Code-Editor und geben Sie die Werte der Umgebungsvariablen mit den Konfigurationswerten aus der Firebase-Konsole ein.
  4. Ersetzen Sie in der Datei die vorhandenen Eigenschaften durch die kopierten.
  5. Speicher die Datei.

Initialisieren Sie die Web-App mit Ihrem Firebase-Projekt

Um die Web-App mit Ihrem Firebase-Projekt zu verbinden, gehen Sie folgendermaßen vor:

  1. Stellen Sie in Ihrem Terminal sicher, dass Web-Frameworks in Firebase aktiviert sind:
    firebase experiments:enable webframeworks
    
  2. Firebase initialisieren:
    firebase init
    
  3. Wählen Sie die folgenden Optionen:
    • Firestore: Konfigurieren Sie Sicherheitsregeln und Indexdateien für Firestore
    • Hosting: Konfigurieren Sie Dateien für Firebase Hosting und richten Sie (optional) GitHub Action-Bereitstellungen ein
    • Speicher: Konfigurieren Sie eine Sicherheitsregeldatei für Cloud Storage
    • Emulatoren: Richten Sie lokale Emulatoren für Firebase-Produkte ein
  4. Wählen Sie „Vorhandenes Projekt verwenden“ aus und geben Sie dann die Projekt-ID ein, die Sie zuvor notiert haben.
  5. Wählen Sie die Standardwerte für alle nachfolgenden Fragen aus, bis Sie zur Frage gelangen . In welcher Region möchten Sie gegebenenfalls serverseitige Inhalte hosten? . Das Terminal zeigt eine Meldung an, dass es eine vorhandene Next.js-Codebasis im aktuellen Verzeichnis erkennt.
  6. Für die Frage : In welcher Region möchten Sie ggf. serverseitige Inhalte hosten? , wählen Sie den Speicherort aus, den Sie zuvor für Firestore und Cloud Storage ausgewählt haben.
  7. Wählen Sie für alle weiteren Fragen die Standardwerte aus, bis Sie bei der Frage „Welche Firebase-Emulatoren möchten Sie einrichten?“ angelangt sind. . Wählen Sie für diese Frage „Funktionsemulator“ und „Hosting-Emulator“ aus.
  8. Wählen Sie für alle anderen Fragen die Standardwerte aus.

Stellen Sie Sicherheitsregeln bereit

Der Code enthält bereits Sätze von Sicherheitsregeln für Firestore und für Cloud Storage für Firebase. Nachdem Sie die Sicherheitsregeln bereitgestellt haben, sind die Daten in Ihrer Datenbank und Ihrem Bucket besser vor Missbrauch geschützt.

  1. Um diese Sicherheitsregeln bereitzustellen, führen Sie diesen Befehl in Ihrem Terminal aus:
    firebase deploy --only firestore:rules,storage
    
  2. Wenn Sie gefragt werden: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" , wählen Sie Ja .

Starten Sie den Hosting-Emulator

  1. Starten Sie in Ihrem Terminal den Hosting-Emulator:
    firebase emulators:start --only hosting
    
    Ihr Terminal antwortet mit dem Port, an dem Sie den Hosting-Emulator finden, zum Beispiel http://localhost:5000/ .

Terminal zeigt an, dass der Hosting-Emulator bereit ist

  1. Navigieren Sie in Ihrem Browser zur URL mit dem Firebase Hosting-Emulator.
  2. Wenn Sie auf der Webseite den Fehler sehen, der wie folgt beginnt: "Error: Firebase session cookie has incorrect..." , müssen Sie alle Ihre Cookies in Ihrer Localhost-Umgebung löschen. Befolgen Sie dazu die Anweisungen unter Cookies löschen | DevTools-Dokumentation .

Ein Cookie-Sitzungsfehler

Cookies in DevTools löschen

Jetzt können Sie die erste Web-App sehen! Auch wenn Sie die Web-App unter einer Localhost-URL anzeigen, verwendet sie echte Firebase-Dienste, die Sie in Ihrer Konsole konfiguriert haben.

6. Fügen Sie der Web-App eine Authentifizierung hinzu

In diesem Abschnitt fügen Sie der Web-App eine Authentifizierung hinzu, damit Sie sich bei ihr anmelden können.

Implementieren Sie die Anmelde- und Abmeldefunktionen

  1. Ersetzen Sie in der Datei src/lib/firebase/auth.js die Funktionen onAuthStateChanged , signInWithGoogle und signOut durch den folgenden Code:
export function onAuthStateChanged(cb) {
        return _onAuthStateChanged(auth, cb);
}

export async function signInWithGoogle() {
        const provider = new GoogleAuthProvider();

        try {
                await signInWithPopup(auth, provider);
        } catch (error) {
                console.error("Error signing in with Google", error);
        }
}

export async function signOut() {
        try {
                return auth.signOut();
        } catch (error) {
                console.error("Error signing out with Google", error);
        }
}

Dieser Code verwendet die folgenden Firebase-APIs:

Firebase-API

Beschreibung

GoogleAuthProvider

Erstellt eine Instanz eines Google-Authentifizierungsanbieters.

signInWithPopup

Startet einen dialogbasierten Authentifizierungsfluss.

auth.signOut

Meldet den Benutzer ab.

In der Datei src/components/Header.jsx ruft der Code bereits die Funktionen signInWithGoogle und signOut auf.

  1. Aktualisieren Sie in der Web-App die Seite und klicken Sie auf Mit Google anmelden . Die Web-App wird nicht aktualisiert, daher ist unklar, ob die Anmeldung erfolgreich war.

Abonnieren Sie Authentifizierungsänderungen

Um Authentifizierungsänderungen zu abonnieren, führen Sie die folgenden Schritte aus:

  1. Navigieren Sie zur Datei src/components/Header.jsx .
  2. Ersetzen Sie die Funktion useUserSession durch den folgenden Code:
function useUserSession(initialUser) {
        // The initialUser comes from the server through a server component
        const [user, setUser] = useState(initialUser);
        const router = useRouter();

        useEffect(() => {
                const unsubscribe = onAuthStateChanged(authUser => {
                        setUser(authUser);
                });
                return () => {
                        unsubscribe();
                };
        }, []);

        useEffect(() => {
                onAuthStateChanged(authUser => {
                        if (user === undefined) return;
                        if (user?.email !== authUser?.email) {
                                router.refresh();
                        }
                });
        }, [user]);

        return user;
}

Dieser Code verwendet einen React- State -Hook, um den Benutzer zu aktualisieren, wenn die Funktion onAuthStateChanged angibt, dass eine Änderung am Authentifizierungsstatus vorliegt.

Änderungen überprüfen

Das Root-Layout in der Datei src/app/layout.js rendert den Header und übergibt den Benutzer, falls verfügbar, als Requisite.

<Header initialUser={currentUser?.toJSON()} />

Dies bedeutet, dass die <Header> -Komponente Benutzerdaten, sofern verfügbar, während der Serverlaufzeit rendert. Wenn es während des Seitenlebenszyklus nach dem ersten Seitenladen Authentifizierungsaktualisierungen gibt, werden diese vom onAuthStateChanged Handler verarbeitet.

Jetzt ist es an der Zeit, die Web-App zu testen und zu überprüfen, was Sie erstellt haben.

Um das neue Authentifizierungsverhalten zu überprüfen, führen Sie die folgenden Schritte aus:

  1. Aktualisieren Sie die Web-App in Ihrem Browser. Ihr Anzeigename erscheint in der Kopfzeile.
  2. Melden Sie sich ab und erneut an. Die Seite wird in Echtzeit aktualisiert, ohne dass eine Seitenaktualisierung erforderlich ist. Sie können diesen Schritt mit verschiedenen Benutzern wiederholen.
  3. Optional: Klicken Sie mit der rechten Maustaste auf die Web-App, wählen Sie Seitenquelle anzeigen aus und suchen Sie nach dem Anzeigenamen. Es erscheint in der vom Server zurückgegebenen Roh-HTML-Quelle.

7. Restaurantinformationen anzeigen

Die Web-App enthält Scheindaten für Restaurants und Bewertungen.

Fügen Sie ein oder mehrere Restaurants hinzu

Führen Sie die folgenden Schritte aus, um Scheinrestaurantdaten in Ihre lokale Cloud Firestore-Datenbank einzufügen:

  1. Wählen Sie in der Web-App aus 2cf67d488d8e6332.png > Beispielrestaurants hinzufügen .
  2. Wählen Sie in der Firebase-Konsole auf der Seite „Firestore-Datenbank“ die Option „restaurants“ aus. Sie sehen die Dokumente der obersten Ebene in der Restaurantsammlung, die jeweils ein Restaurant darstellen.
  3. Klicken Sie auf einige Dokumente, um die Eigenschaften eines Restaurantdokuments zu erkunden.

Zeigen Sie die Liste der Restaurants an

Ihre Cloud Firestore-Datenbank verfügt jetzt über Restaurants, die die Next.js-Web-App anzeigen kann.

Um den Datenabrufcode zu definieren, führen Sie die folgenden Schritte aus:

  1. Suchen Sie in der Datei src/app/page.js nach der Serverkomponente <Home /> und überprüfen Sie den Aufruf der getRestaurants Funktion, die zur Serverlaufzeit eine Liste von Restaurants abruft. In den folgenden Schritten implementieren Sie die Funktion getRestaurants .
  2. Ersetzen Sie in der Datei src/lib/firebase/firestore.js die Funktionen applyQueryFilters und getRestaurants durch den folgenden Code:
function applyQueryFilters(q, { category, city, price, sort }) {
        if (category) {
                q = query(q, where("category", "==", category));
        }
        if (city) {
                q = query(q, where("city", "==", city));
        }
        if (price) {
                q = query(q, where("price", "==", price.length));
        }
        if (sort === "Rating" || !sort) {
                q = query(q, orderBy("avgRating", "desc"));
        } else if (sort === "Review") {
                q = query(q, orderBy("numRatings", "desc"));
        }
        return q;
}

export async function getRestaurants(filters = {}) {
        let q = query(collection(db, "restaurants"));

        q = applyQueryFilters(q, filters);
        const results = await getDocs(q);
        return results.docs.map(doc => {
                return {
                        id: doc.id,
                        ...doc.data(),
                        // Only plain objects can be passed to Client Components from Server Components
                        timestamp: doc.data().timestamp.toDate(),
                };
        });
}
  1. Aktualisieren Sie die Web-App. Restaurantbilder erscheinen als Kacheln auf der Seite.

Stellen Sie sicher, dass die Restauranteinträge zur Serverlaufzeit geladen werden

Bei Verwendung des Next.js-Frameworks ist es möglicherweise nicht offensichtlich, wann Daten zur Serverlaufzeit oder zur clientseitigen Laufzeit geladen werden.

Um zu überprüfen, ob Restauranteinträge zur Serverlaufzeit geladen werden, führen Sie die folgenden Schritte aus:

  1. Öffnen Sie in der Web-App DevTools und deaktivieren Sie JavaScript .

Deaktivieren Sie JavaScipt in DevTools

  1. Aktualisieren Sie die Web-App. Die Restauranteinträge werden weiterhin geladen. Restaurantinformationen werden in der Serverantwort zurückgegeben. Wenn JavaScript aktiviert ist, werden die Restaurantinformationen durch den clientseitigen JavaScript-Code hydratisiert .
  2. Aktivieren Sie in DevTools JavaScript erneut .

Hören Sie mit Cloud Firestore-Snapshot-Listenern auf Restaurant-Updates

Im vorherigen Abschnitt haben Sie gesehen, wie die anfängliche Gruppe von Restaurants aus der Datei src/app/page.js geladen wurde. Die Datei src/app/page.js ist eine Serverkomponente und wird auf dem Server gerendert, einschließlich des Firebase-Datenabrufcodes.

Die Datei src/components/RestaurantListings.jsx ist eine Client-Komponente und kann so konfiguriert werden, dass vom Server gerendertes Markup hydratisiert wird.

Führen Sie die folgenden Schritte aus, um die Datei src/components/RestaurantListings.jsx so zu konfigurieren, dass vom Server gerendertes Markup hydratisiert wird:

  1. Beachten Sie in der Datei src/components/RestaurantListings.jsx den folgenden Code, der bereits für Sie geschrieben wurde:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

        return () => {
                unsubscribe();
        };
}, [filters]);

Dieser Code ruft die Funktion getRestaurantsSnapshot() auf, die der Funktion getRestaurants() ähnelt, die Sie in einem vorherigen Schritt implementiert haben. Diese Snapshot-Funktion bietet jedoch einen Rückrufmechanismus, sodass der Rückruf jedes Mal aufgerufen wird, wenn eine Änderung an der Sammlung des Restaurants vorgenommen wird.

  1. Ersetzen Sie in der Datei src/lib/firebase/firestore.js die Funktion getRestaurantsSnapshot() durch den folgenden Code:
export function getRestaurantsSnapshot(cb, filters = {}) {
        if (typeof cb !== "function") {
                console.log("Error: The callback parameter is not a function");
                return;
        }

        let q = query(collection(db, "restaurants"));
        q = applyQueryFilters(q, filters);

        const unsubscribe = onSnapshot(q, querySnapshot => {
                const results = querySnapshot.docs.map(doc => {
                        return {
                                id: doc.id,
                                ...doc.data(),
                                // Only plain objects can be passed to Client Components from Server Components
                                timestamp: doc.data().timestamp.toDate(),
                        };
                });

                cb(results);
        });

        return unsubscribe;
}

Über die Firestore-Datenbankseite vorgenommene Änderungen werden jetzt in Echtzeit in der Web-App angezeigt.

  1. Wählen Sie in der Web-App aus 27ca5d1e8ed8adfe.png > Beispielrestaurants hinzufügen . Wenn Ihre Snapshot-Funktion korrekt implementiert ist, werden die Restaurants in Echtzeit angezeigt, ohne dass eine Seitenaktualisierung erforderlich ist.

8. Benutzerdaten aus der Web-App speichern

  1. Ersetzen Sie in der Datei src/lib/firebase/firestore.js die Funktion updateWithRating() durch den folgenden Code:
const updateWithRating = async (
        transaction,
        docRef,
        newRatingDocument,
        review
) => {
        const restaurant = await transaction.get(docRef);
        const data = restaurant.data();
        const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
        const newSumRating = (data?.sumRating || 0) + Number(review.rating);
        const newAverage = newSumRating / newNumRatings;

        transaction.update(docRef, {
                numRatings: newNumRatings,
                sumRating: newSumRating,
                avgRating: newAverage,
        });

        transaction.set(newRatingDocument, {
                ...review,
                timestamp: Timestamp.fromDate(new Date()),
        });
};

Dieser Code fügt ein neues Firestore-Dokument ein, das die neue Rezension darstellt. Der Code aktualisiert außerdem das vorhandene Firestore-Dokument, das das Restaurant darstellt, mit aktualisierten Zahlen für die Anzahl der Bewertungen und die durchschnittlich berechnete Bewertung.

  1. Ersetzen Sie die Funktion addReviewToRestaurant() durch den folgenden Code:
export async function addReviewToRestaurant(db, restaurantId, review) {
        if (!restaurantId) {
                throw new Error("No restaurant ID was provided.");
        }

        if (!review) {
                throw new Error("A valid review has not been provided.");
        }

        try {
                const docRef = doc(collection(db, "restaurants"), restaurantId);
                const newRatingDocument = doc(
                        collection(db, `restaurants/${restaurantId}/ratings`)
                );

                await runTransaction(db, transaction =>
                        updateWithRating(transaction, docRef, newRatingDocument, review)
                );
        } catch (error) {
                console.error(
                        "There was an error adding the rating to the restaurant.",
                        error
                );
                throw error;
        }
}

Implementieren Sie eine Next.js-Serveraktion

Eine Next.js-Serveraktion bietet eine praktische API für den Zugriff auf Formulardaten, z. data.get("text") um den Textwert aus der Nutzlast der Formularübermittlung abzurufen.

Um eine Next.js-Serveraktion zum Verarbeiten der Übermittlung des Überprüfungsformulars zu verwenden, führen Sie die folgenden Schritte aus:

  1. Suchen Sie in der Datei src/components/ReviewDialog.jsx das action im Element <form> .
<form action={handleReviewFormSubmission}>

Der Wert des action bezieht sich auf eine Funktion, die Sie im nächsten Schritt implementieren.

  1. Ersetzen Sie in der Datei src/app/actions.js die Funktion handleReviewFormSubmission() durch den folgenden Code:
// This is a next.js server action, which is an alpha feature, so
// use with caution.
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
export async function handleReviewFormSubmission(data) {
        const { app } = await getAuthenticatedAppForUser();
        const db = getFirestore(app);

        await addReviewToRestaurant(db, data.get("restaurantId"), {
                text: data.get("text"),
                rating: data.get("rating"),

                // This came from a hidden form field.
                userId: data.get("userId"),
        });
}

Fügen Sie Bewertungen für ein Restaurant hinzu

Sie haben die Unterstützung für Bewertungseinreichungen implementiert, sodass Sie jetzt überprüfen können, ob Ihre Bewertungen korrekt in Cloud Firestore eingefügt werden.

Führen Sie die folgenden Schritte aus, um eine Rezension hinzuzufügen und zu überprüfen, ob sie in Cloud Firestore eingefügt wurde:

  1. Wählen Sie in der Web-App auf der Startseite ein Restaurant aus.
  2. Klicken Sie auf der Seite des Restaurants auf 3e19beef78bb0d0e.png .
  3. Wählen Sie eine Sternebewertung aus.
  4. Eine Rezension schreiben.
  5. Klicken Sie auf „Senden“ . Ihre Bewertung erscheint oben in der Liste der Bewertungen.
  6. Suchen Sie in Cloud Firestore im Bereich „Dokument hinzufügen“ nach dem Dokument des Restaurants, das Sie überprüft haben, und wählen Sie es aus.
  7. Wählen Sie im Bereich „Sammlung starten“ die Option „Bewertungen“ aus.
  8. Suchen Sie im Bereich „Dokument hinzufügen“ nach dem Dokument, das Sie überprüfen möchten, um zu überprüfen, ob es wie erwartet eingefügt wurde.

Dokumente im Firestore-Emulator

9. Speichern Sie vom Benutzer hochgeladene Dateien aus der Web-App

In diesem Abschnitt fügen Sie Funktionen hinzu, damit Sie das mit einem Restaurant verknüpfte Bild ersetzen können, wenn Sie angemeldet sind. Sie laden das Bild in Firebase Storage hoch und aktualisieren die Bild-URL im Cloud Firestore-Dokument, das das Restaurant darstellt.

Gehen Sie folgendermaßen vor, um vom Benutzer hochgeladene Dateien aus der Web-App zu speichern:

  1. Beobachten Sie in der Datei src/components/Restaurant.jsx den Code, der ausgeführt wird, wenn der Benutzer eine Datei hochlädt:
async function handleRestaurantImage(target) {
        const image = target.files ? target.files[0] : null;
        if (!image) {
                return;
        }

        const imageURL = await updateRestaurantImage(id, image);
        setRestaurant({ ...restaurant, photo: imageURL });
}

Es sind keine Änderungen erforderlich, aber Sie implementieren das Verhalten der Funktion updateRestaurantImage() in den folgenden Schritten.

  1. Ersetzen Sie in der Datei src/lib/firebase/storage.js die Funktionen updateRestaurantImage() und uploadImage() durch den folgenden Code:
export async function updateRestaurantImage(restaurantId, image) {
        try {
                if (!restaurantId)
                        throw new Error("No restaurant ID has been provided.");

                if (!image || !image.name)
                        throw new Error("A valid image has not been provided.");

                const publicImageUrl = await uploadImage(restaurantId, image);
                await updateRestaurantImageReference(restaurantId, publicImageUrl);

                return publicImageUrl;
        } catch (error) {
                console.error("Error processing request:", error);
        }
}

async function uploadImage(restaurantId, image) {
        const filePath = `images/${restaurantId}/${image.name}`;
        const newImageRef = ref(storage, filePath);
        await uploadBytesResumable(newImageRef, image);

        return await getDownloadURL(newImageRef);
}

Die Funktion updateRestaurantImageReference() ist bereits für Sie implementiert. Diese Funktion aktualisiert ein vorhandenes Restaurantdokument in Cloud Firestore mit einer aktualisierten Bild-URL.

Überprüfen Sie die Funktion zum Hochladen von Bildern

Um zu überprüfen, ob das Bild wie erwartet hochgeladen wird, führen Sie die folgenden Schritte aus:

  1. Vergewissern Sie sich in der Web-App, dass Sie angemeldet sind, und wählen Sie ein Restaurant aus.
  2. Klicken 7067eb41fea41ff0.png und laden Sie ein Bild aus Ihrem Dateisystem hoch. Ihr Bild verlässt Ihre lokale Umgebung und wird in den Cloud-Speicher hochgeladen. Das Bild erscheint sofort nach dem Hochladen.
  3. Navigieren Sie zu Cloud Storage für Firebase.
  4. Navigieren Sie zu dem Ordner, der das Restaurant darstellt. Das von Ihnen hochgeladene Bild ist im Ordner vorhanden.

6cf3f9e2303c931c.png

10. Fazit

Glückwunsch! Sie haben gelernt, wie Sie mit Firebase Features und Funktionen zu einer Next.js-App hinzufügen. Konkret haben Sie Folgendes verwendet:

Erfahren Sie mehr