1. Hinweis
In diesem Codelab erfahren Sie, wie Sie Firebase in die Next.js-Web-App Friendly Eats einbinden. Hierbei handelt es sich um eine Website für Restaurantbewertungen.
Die fertige Webanwendung bietet nützliche Funktionen, die zeigen, wie Sie mit Firebase Next.js-Apps erstellen können. Zu diesen Funktionen gehören:
- Automatischer Build und automatische Bereitstellung: In diesem Codelab wird Firebase App Hosting verwendet, um Ihren Next.js-Code jedes Mal automatisch zu erstellen und bereitzustellen, wenn Sie einen Commit auf einen konfigurierten Branch ausführen.
- An- und Abmelden:Mit der fertigen Web-App können Sie sich über Google an- und abmelden. Nutzeranmeldung und Persistenz werden vollständig über Firebase Authentication verwaltet.
- Bilder: In der fertigen Webanwendung können angemeldete Nutzer Bilder von Restaurants hochladen. Bild-Assets werden in Cloud Storage for Firebase gespeichert. Das Firebase JavaScript SDK stellt eine öffentliche URL zu hochgeladenen Bildern bereit. Diese öffentliche URL wird dann im entsprechenden Restaurantdokument in Cloud Firestore gespeichert.
- Rezensionen: In der fertigen Web-App können angemeldete Nutzer Rezensionen zu Restaurants posten, die aus einer Sternebewertung und einer textbasierten Nachricht bestehen. Überprüfungsinformationen werden in Cloud Firestore gespeichert.
- Filter: In der fertigen Web-App können angemeldete Nutzer 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.
Vorbereitung
- Ein GitHub-Konto
- Kenntnisse in Next.js und JavaScript
Lerninhalte
- Firebase mit dem Next.js App Router und serverseitigem Rendering verwenden
- So speichern Sie Images in Cloud Storage for Firebase dauerhaft.
- Daten in einer Cloud Firestore-Datenbank lesen und schreiben
- Hier erfahren Sie, wie Sie die Anmeldung über Google mit dem Firebase JavaScript SDK verwenden.
Voraussetzungen
- Git
- Eine aktuelle stabile Version von Node.js
- Browser Ihrer Wahl, z. B. Google Chrome
- Eine Entwicklungsumgebung mit einem Code-Editor und einem Terminal
- Ein Google-Konto zum Erstellen und Verwalten Ihres Firebase-Projekts
- Sie können Ihr Firebase-Projekt auf den Blaze-Tarif umstellen.
2. Entwicklungsumgebung und GitHub-Repository einrichten
Dieses Codelab enthält die Starter-Codebasis der App und basiert auf der Firebase CLI.
GitHub-Repository erstellen
Den Quellcode des Codelab finden Sie unter https://github.com/firebase/Friendlyeats-web. Das Repository enthält Beispielprojekte für mehrere Plattformen. In diesem Codelab wird jedoch nur das Verzeichnis nextjs-start
verwendet. Beachten Sie die folgenden Verzeichnisse:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Kopieren Sie den Ordner nextjs-start
in Ihr eigenes Repository:
- Erstellen Sie über ein Terminal einen neuen Ordner auf Ihrem Computer und wechseln Sie in das neue Verzeichnis:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web
- Verwenden Sie das npm-Paket giget, um nur den Ordner
nextjs-start
abzurufen:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- Verfolgen Sie Änderungen lokal mit Git:
git init git commit -a -m "codelab starting point" git branch -M main
- Erstellen Sie ein neues GitHub-Repository: https://github.com/new. Sie können ihm einen beliebigen Namen geben.
- Sie erhalten von GitHub eine neue Repository-URL, die entweder
https://github.com/
oder/ .git git@github.com:
lautet. Kopieren Sie diese URL./ .git
- Sie erhalten von GitHub eine neue Repository-URL, die entweder
- Übertragen Sie lokale Änderungen per Push in Ihr neues GitHub-Repository. Führen Sie den folgenden Befehl aus und ersetzen Sie dabei die Repository-URL durch den Platzhalter
.git remote add origin <your-repository-url> git push -u origin main
- Der Startcode sollte jetzt in Ihrem GitHub-Repository angezeigt werden.
Firebase CLI installieren oder aktualisieren
Führen Sie den folgenden Befehl aus, um zu prüfen, ob die Firebase CLI installiert ist und Version 13.9.0 oder höher installiert ist:
firebase --version
Wenn eine niedrigere Version angezeigt wird oder Firebase CLI nicht installiert ist, führen Sie den Installationsbefehl aus:
npm install -g firebase-tools@latest
Wenn Sie die Firebase CLI aufgrund von Berechtigungsfehlern nicht installieren können, lesen Sie die npm-Dokumentation oder verwenden Sie eine andere Installationsoption.
In Firebase anmelden
- Führen Sie den folgenden Befehl aus, um sich in der Firebase CLI anzumelden:
firebase login
- Geben Sie
Y
oderN
ein, je nachdem, ob Firebase Daten erheben soll. - Wählen Sie im Browser Ihr Google-Konto aus und klicken Sie dann auf Zulassen.
3. Das Firebase-Projekt einrichten
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.
Firebase-Projekt erstellen
- Klicken Sie in der Firebase Console auf Projekt hinzufügen.
- Geben Sie im Textfeld Projektnamen eingeben
FriendlyEats Codelab
(oder einen beliebigen Projektnamen) ein und klicken Sie auf Weiter. - Bestätigen Sie im modalen Fenster Firebase-Tarif bestätigen, dass es sich um Blaze handelt, und klicken Sie dann auf Tarif bestätigen.
- Für dieses Codelab benötigen Sie kein Google Analytics. Deaktivieren Sie daher die Option Google Analytics für dieses Projekt aktivieren.
- Klicken Sie auf Projekt erstellen.
- Warten Sie, bis Ihr Projekt bereitgestellt wurde, und klicken Sie dann auf Weiter.
- Rufen Sie in Ihrem Firebase-Projekt die Projekteinstellungen auf. Notieren Sie sich Ihre Projekt-ID, da Sie diese später benötigen. Anhand dieser eindeutigen Kennung wird Ihr Projekt identifiziert, z. B. in der Firebase CLI.
Firebase-Preismodell upgraden
Wenn Sie Firebase App Hosting und Cloud Storage for Firebase verwenden möchten, muss für Ihr Firebase-Projekt das „Pay as you go“-Preismodell (Blaze) verwendet werden. Das bedeutet, dass es mit einem Cloud-Rechnungskonto verknüpft ist.
- Für ein Cloud-Rechnungskonto ist eine Zahlungsmethode erforderlich, z. B. eine Kreditkarte.
- Wenn Sie neu bei Firebase und Google Cloud sind, prüfen Sie, ob Sie Anspruch auf ein Guthaben in Höhe von 300 $ und ein kostenloses Cloud Billing-Konto haben.
- Wenn Sie dieses Codelab im Rahmen einer Veranstaltung absolvieren, fragen Sie Ihren Organisator, ob Cloud-Guthaben verfügbar ist.
So führen Sie ein Upgrade auf den Blaze-Tarif durch:
- Wählen Sie in der Firebase Console Tarif upgraden aus.
- Wählen Sie den Tarif „Blaze“ aus. Folgen Sie der Anleitung auf dem Bildschirm, um ein Cloud-Rechnungskonto mit Ihrem Projekt zu verknüpfen.
Wenn Sie im Rahmen dieses Upgrades ein Cloud-Rechnungskonto erstellen mussten, müssen Sie möglicherweise zum Upgradevorgang in der Firebase Console zurückkehren, um das Upgrade abzuschließen.
Ihrem Firebase-Projekt eine Web-App hinzufügen
- Rufen Sie in Ihrem Firebase-Projekt die Projektübersicht auf und klicken Sie dann auf Web.
Wenn in Ihrem Projekt bereits Apps registriert sind, klicken Sie auf App hinzufügen, um das Websymbol zu sehen. - Geben Sie im Textfeld App-Alias einen einprägsamen Alias für die App ein, z. B.
My Next.js app
. - Lassen Sie das Kästchen Richten Sie außerdem Firebase Hosting für diese App ein deaktiviert.
- Klicken Sie auf App registrieren > Weiter > Weiter > Weiter zur Konsole.
Firebase-Dienste in der Firebase Console einrichten
Authentifizierung einrichten
- Gehen Sie in der Firebase Console zu Authentifizierung.
- Klicken Sie auf Starten.
- Klicken Sie in der Spalte Zusätzliche Anbieter auf Google > Aktivieren.
- Geben Sie im Textfeld Öffentlicher Name für Projekt einen einprägsamen Namen wie
My Next.js app
ein. - Wählen Sie im Drop-down-Menü Support-E-Mail-Adresse für das Projekt Ihre E-Mail-Adresse aus.
- Klicken Sie auf Speichern.
Cloud Firestore einrichten
- Maximieren Sie im linken Bereich der Firebase Console Build und wählen Sie dann Firestore-Datenbank aus.
- Klicken Sie auf Datenbank erstellen.
- Lassen Sie die Datenbank-ID auf
(default)
. - Wählen Sie einen Speicherort für die Datenbank aus und klicken Sie auf Weiter.
Für eine echte App sollten Sie einen Speicherort in der Nähe Ihrer Nutzer auswählen. - Klicken Sie auf Im Testmodus starten. Lesen Sie den Haftungsausschluss zu den Sicherheitsregeln.
Später in diesem Codelab fügen Sie Sicherheitsregeln hinzu, um Ihre Daten zu schützen. Veröffentlichen oder verteilen Sie keine App, ohne Sicherheitsregeln für Ihre Datenbank hinzuzufügen. - Klicken Sie auf Erstellen.
Cloud Storage for Firebase einrichten
- Maximieren Sie im linken Bereich der Firebase Console die Option Build und wählen Sie dann Storage aus.
- Klicken Sie auf Starten.
- Wählen Sie einen Speicherort für Ihren Standard-Storage-Bucket aus.
Buckets inUS-WEST1
,US-CENTRAL1
undUS-EAST1
können die Stufe „Immer kostenlos“ für Google Cloud Storage nutzen. Für Buckets an allen anderen Speicherorten gelten die Preise und Nutzungsbedingungen für Google Cloud Storage. - Klicken Sie auf Im Testmodus starten. Lesen Sie den Haftungsausschluss zu den Sicherheitsregeln.
Später in diesem Codelab fügen Sie Sicherheitsregeln hinzu, um Ihre Daten zu schützen. Veröffentlichen oder verteilen Sie keine App, ohne Sicherheitsregeln für Ihren Speicher-Bucket hinzuzufügen. - Klicken Sie auf Erstellen.
4. Starter-Codebasis ansehen
In diesem Abschnitt sehen Sie sich einige Bereiche der Startcodebasis der App an, denen Sie in diesem Codelab Funktionen hinzufügen.
Ordner- und Dateistruktur
Die folgende Tabelle enthält einen Überblick über die Ordner- und Dateistruktur der App:
Ordner und Dateien | Beschreibung |
| React-Komponenten für Filter, Überschriften, Restaurantdetails und Rezensionen |
| Dienstprogrammfunktionen, die nicht unbedingt an React oder Next.js gebunden sind |
| Firebase-spezifischer Code und Firebase-Konfiguration |
| Statische Assets in der Web-App, z. B. Symbole |
| Routing mit dem Next.js App Router |
| Einen API-Route-Handler |
| Projektabhängigkeiten mit npm |
| Next.js-spezifische Konfiguration (Serveraktionen sind aktiviert) |
| Konfiguration des JavaScript-Sprachdienstes |
Server- und Clientkomponenten
Die App ist eine Next.js-Web-App, die den App Router verwendet. Das serverseitige Rendering wird in der gesamten App verwendet. Die Datei src/app/page.js
ist beispielsweise eine Serverkomponente, die für die Startseite verantwortlich ist. Die Datei src/components/RestaurantListings.jsx
ist eine Clientkomponente, die durch die Anweisung "use client"
am Anfang der Datei angegeben wird.
Importanweisungen
Möglicherweise sehen Sie Importanweisungen wie die folgenden:
import RatingPicker from "@/src/components/RatingPicker.jsx";
In der App wird das Symbol @
verwendet, um unübersichtliche relative Importpfade zu vermeiden. Dies wird durch Pfadaliasse ermöglicht.
Firebase-spezifische APIs
Der gesamte Firebase API-Code wird im Verzeichnis src/lib/firebase
verpackt. Einzelne React-Komponenten importieren dann die verpackten Funktionen aus dem Verzeichnis src/lib/firebase
, anstatt Firebase-Funktionen direkt zu importieren.
Beispieldaten
Die Daten zu fiktiven Restaurants und Rezensionen sind in der Datei src/lib/randomData.js
enthalten. Die Daten aus dieser Datei werden im Code in der Datei src/lib/fakeRestaurants.js
zusammengestellt.
5. App-Hosting-Backend erstellen
In diesem Abschnitt richten Sie ein App Hosting-Backend ein, um einen Zweig in Ihrem Git-Repository zu beobachten.
Am Ende dieses Abschnitts haben Sie ein App Hosting-Backend, das mit Ihrem Repository in GitHub verbunden ist und automatisch eine neue Version Ihrer App neu erstellt und bereitstellt, wenn Sie einen neuen Commit an Ihren main
-Branch übertragen.
Sicherheitsregeln bereitstellen
Der Code enthält bereits Sicherheitsregeln für Firestore und Cloud Storage for Firebase. Nach der Bereitstellung der Sicherheitsregeln sind die Daten in Ihrer Datenbank und Ihrem Bucket besser vor Missbrauch geschützt.
- Konfigurieren Sie in Ihrem Terminal die Befehlszeile, um das zuvor erstellte Firebase-Projekt zu verwenden:
Geben Sie bei Aufforderung nach einem Aliasfirebase use --add
friendlyeats-codelab
ein. - Führen Sie den folgenden Befehl in Ihrem Terminal aus, um diese Sicherheitsregeln bereitzustellen:
firebase deploy --only firestore:rules,storage
- Wenn Sie gefragt werden:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"
, drücken SieEnter
, um Ja auszuwählen.
Firebase-Konfiguration in den Code Ihrer Webanwendung einfügen
- Rufen Sie in der Firebase Console die Projekteinstellungen auf.
- Klicken Sie im Bereich SDK-Einrichtung und -Konfiguration auf „App hinzufügen“ und dann auf das Symbol mit den eckigen Klammern
, um eine neue Web-App zu registrieren.
- Kopieren Sie am Ende des Erstellungsvorgangs für die Web-App die Variable
firebaseConfig
und kopieren Sie ihre Eigenschaften und ihre Werte. - Öffnen Sie die Datei
apphosting.yaml
in Ihrem Code-Editor und tragen Sie die Werte der Umgebungsvariablen mit den Konfigurationswerten aus der Firebase Console ein. - Ersetzen Sie in der Datei die vorhandenen Properties durch die kopierten.
- Speichern Sie die Datei.
Backend erstellen
- Rufen Sie in der Firebase Console die Seite App-Hosting auf:
- Klicken Sie auf „Jetzt starten“, um mit dem Erstellen des Back-Ends zu beginnen. Konfigurieren Sie Ihr Backend so:
- Folgen Sie der Anleitung im ersten Schritt, um das zuvor erstellte GitHub-Repository zu verbinden.
- Legen Sie die Bereitstellungseinstellungen fest:
- Stammverzeichnis bei
/
belassen - Legen Sie den Live-Zweig auf
main
fest. - Automatische Roll-outs aktivieren
- Stammverzeichnis bei
- Benennen Sie das Backend
friendlyeats-codelab
. - Wählen Sie unter „Firebase Web-App erstellen oder verknüpfen“ die Web-App aus, die Sie zuvor aus dem Drop-down-Menü „Vorhandene Firebase Web-App auswählen“ konfiguriert haben.
- Klicken Sie auf „Fertigstellen und bereitstellen“. Nach kurzer Zeit werden Sie auf eine neue Seite weitergeleitet, auf der Sie den Status Ihres neuen App Hosting-Backends sehen können.
- Klicken Sie nach Abschluss der Einführung unter „Domains“ auf Ihre kostenlose Domain. Aufgrund der DNS-Weitergabe kann es einige Minuten dauern, bis dies funktioniert.
Sie haben die erste Webanwendung bereitgestellt. Jedes Mal, wenn Sie per Push einen neuen Commit an den main
-Zweig Ihres GitHub-Repositorys senden, werden in der Firebase Console ein neuer Build und ein Roll-out gestartet. Ihre Website wird nach Abschluss des Roll-outs automatisch aktualisiert.
6. Authentifizierung für die Webanwendung hinzufügen
In diesem Abschnitt fügen Sie der Webanwendung eine Authentifizierung hinzu, damit Sie sich darin anmelden können.
Anmelde- und Abmeldefunktionen implementieren
- Ersetzen Sie in der Datei
src/lib/firebase/auth.js
die FunktionenonAuthStateChanged
,signInWithGoogle
undsignOut
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);
}
}
In diesem Code werden die folgenden Firebase APIs verwendet:
Firebase API | Beschreibung |
Erstellt eine Instanz des Google-Authentifizierungsanbieters. | |
Startet einen dialogbasierten Authentifizierungsvorgang. | |
Der Nutzer wird abgemeldet. |
In der Datei src/components/Header.jsx
ruft der Code bereits die Funktionen signInWithGoogle
und signOut
auf.
- Erstellen Sie einen Commit mit der Commit-Nachricht „Google-Authentifizierung hinzufügen“ und pushen Sie ihn in Ihr GitHub-Repository. 1. Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Aktualisieren Sie die Seite in der Webanwendung und klicken Sie auf Über Google anmelden. Die Webanwendung wird nicht aktualisiert, sodass nicht klar ist, ob die Anmeldung erfolgreich war.
Authentifizierungsstatus an Server senden
Um den Authentifizierungsstatus an den Server weiterzugeben, verwenden wir einen Dienst-Worker. Ersetzen Sie die Funktionen fetchWithFirebaseHeaders
und getAuthIdToken
durch den folgenden Code:
async function fetchWithFirebaseHeaders(request) {
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const installations = getInstallations(app);
const headers = new Headers(request.headers);
const [authIdToken, installationToken] = await Promise.all([
getAuthIdToken(auth),
getToken(installations),
]);
headers.append("Firebase-Instance-ID-Token", installationToken);
if (authIdToken) headers.append("Authorization", `Bearer ${authIdToken}`);
const newRequest = new Request(request, { headers });
return await fetch(newRequest);
}
async function getAuthIdToken(auth) {
await auth.authStateReady();
if (!auth.currentUser) return;
return await getIdToken(auth.currentUser);
}
Authentifizierungsstatus auf dem Server lesen
Wir verwenden FirebaseServerApp, um den Authentifizierungsstatus des Clients auf dem Server zu spiegeln.
Öffnen Sie src/lib/firebase/serverApp.js
und ersetzen Sie die Funktion getAuthenticatedAppForUser
:
export async function getAuthenticatedAppForUser() {
const idToken = headers().get("Authorization")?.split("Bearer ")[1];
console.log('firebaseConfig', JSON.stringify(firebaseConfig));
const firebaseServerApp = initializeServerApp(
firebaseConfig,
idToken
? {
authIdToken: idToken,
}
: {}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
Benachrichtigungen zu Authentifizierungsänderungen abonnieren
So abonnieren Sie Authentifizierungsänderungen:
- Rufen Sie die Datei
src/components/Header.jsx
auf. - Ersetzen Sie die Funktion
useUserSession
durch den folgenden Code:
function useUserSession(initialUser) {
// The initialUser comes from the server via a server component
const [user, setUser] = useState(initialUser);
const router = useRouter();
// Register the service worker that sends auth state back to server
// The service worker is built with npm run build-service-worker
useEffect(() => {
if ("serviceWorker" in navigator) {
const serializedFirebaseConfig = encodeURIComponent(JSON.stringify(firebaseConfig));
const serviceWorkerUrl = `/auth-service-worker.js?firebaseConfig=${serializedFirebaseConfig}`
navigator.serviceWorker
.register(serviceWorkerUrl)
.then((registration) => console.log("scope is: ", registration.scope));
}
}, []);
useEffect(() => {
const unsubscribe = onAuthStateChanged((authUser) => {
setUser(authUser)
})
return () => unsubscribe()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
onAuthStateChanged((authUser) => {
if (user === undefined) return
// refresh when user changed to ease testing
if (user?.email !== authUser?.email) {
router.refresh()
}
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user])
return user;
}
In diesem Code wird ein State-Hook von React verwendet, um den Nutzer zu aktualisieren, wenn die onAuthStateChanged
-Funktion angibt, dass sich der Authentifizierungsstatus geändert hat.
Änderungen prüfen
Das Stamm-Layout in der src/app/layout.js
-Datei rendert den Header und gibt den Nutzer, falls verfügbar, als Prop weiter.
<Header initialUser={currentUser?.toJSON()} />
Das bedeutet, dass die Komponente „<Header>
“ Nutzerdaten, sofern verfügbar, während der Serverlaufzeit rendert. Wenn nach dem ersten Seitenaufbau während des Seitenlebenszyklus Authentifizierungsaktualisierungen auftreten, werden diese vom onAuthStateChanged
-Handler verarbeitet.
Jetzt ist es an der Zeit, einen neuen Build einzuführen und zu prüfen, was Sie erstellt haben.
- Erstellen Sie einen Commit mit der Commit-Nachricht „Anmeldestatus anzeigen“ und übertragen Sie ihn per Push in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Überprüfen Sie das neue Authentifizierungsverhalten:
- Aktualisieren Sie die Web-App im Browser. Ihr Anzeigename wird in der Kopfzeile angezeigt.
- Melden Sie sich ab und wieder an. Die Seite wird in Echtzeit und ohne Aktualisierung der Seite aktualisiert. Sie können diesen Schritt mit verschiedenen Nutzern wiederholen.
- Optional: Klicken Sie mit der rechten Maustaste auf die Web-App, wählen Sie Seitenquelltext anzeigen aus und suchen Sie nach dem Anzeigenamen. Er erscheint in der HTML-Rohquelle, die vom Server zurückgegeben wird.
7. Restaurantinformationen ansehen
Die Web-App enthält Beispieldaten für Restaurants und Rezensionen.
Ein oder mehrere Restaurants hinzufügen
So fügen Sie simulierte Restaurantdaten in Ihre lokale Cloud Firestore-Datenbank ein:
- Wählen Sie in der Webanwendung > Beispielrestaurants hinzufügen aus.
- Wählen Sie in der Firebase Console auf der Seite Firestore-Datenbank die Option restaurants aus. Sie sehen die Dokumente der obersten Ebene in der Sammlung „Restaurants“, die jeweils ein Restaurant repräsentieren.
- Klicken Sie auf einige Dokumente, um die Eigenschaften eines Restaurantdokuments zu sehen.
Liste der Restaurants anzeigen
Ihre Cloud Firestore-Datenbank enthält jetzt Restaurants, die von der Next.js-Webanwendung angezeigt werden können.
So definieren Sie den Code zum Abrufen von Daten:
- Suchen Sie in der Datei
src/app/page.js
nach der Serverkomponente<Home />
und prüfen Sie den Aufruf der FunktiongetRestaurants
, die bei der Serverausführung eine Liste von Restaurants abruft. In den folgenden Schritten implementieren Sie die FunktiongetRestaurants
. - Ersetzen Sie in der Datei
src/lib/firebase/firestore.js
die FunktionenapplyQueryFilters
undgetRestaurants
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(db = db, 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(),
};
});
}
- Erstellen Sie einen Commit mit der Commit-Nachricht „Liste der Restaurants aus Firestore lesen“ und pushen Sie ihn in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Aktualisieren Sie die Seite in der Webanwendung. Restaurantbilder werden auf der Seite als Kacheln angezeigt.
Prüfen, ob die Restauranteinträge zur Laufzeit des Servers geladen werden
Bei Verwendung des Next.js-Frameworks ist es möglicherweise nicht offensichtlich, wenn Daten zur Server- oder clientseitigen Laufzeit geladen werden.
So prüfen Sie, ob Restauranteinträge zur Serverlaufzeit geladen werden:
- Öffnen Sie in der Webanwendung die Entwicklertools und deaktivieren Sie JavaScript.
- Aktualisieren Sie die Webanwendung. Die Restauranteinträge werden weiterhin geladen. Die Restaurantinformationen werden in der Serverantwort zurückgegeben. Wenn JavaScript aktiviert ist, werden die Restaurantinformationen über den clientseitigen JavaScript-Code hydriert.
- Aktivieren Sie JavaScript in den Entwicklertools wieder.
Mit Cloud Firestore-Snapshot-Listenern auf Restaurantupdates warten
Im vorherigen Abschnitt haben Sie gesehen, wie die ersten Restaurants aus der Datei src/app/page.js
geladen wurden. Die src/app/page.js
-Datei ist eine Serverkomponente und wird auf dem Server gerendert, einschließlich des Firebase-Codes zum Abrufen von Daten.
Die src/components/RestaurantListings.jsx
-Datei ist eine Clientkomponente und kann so konfiguriert werden, dass serverseitig gerendertes Markup hydratisiert wird.
So konfigurierst du die Datei src/components/RestaurantListings.jsx
für die Bereitstellung des vom Server gerenderten Markups:
- Sehen Sie sich in der Datei
src/components/RestaurantListings.jsx
den folgenden Code an, der bereits für Sie geschrieben ist:
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 Callback-Mechanismus, sodass der Callback jedes Mal aufgerufen wird, wenn eine Änderung an der Sammlung des Restaurants vorgenommen wird.
- Ersetzen Sie in der Datei
src/lib/firebase/firestore.js
die FunktiongetRestaurantsSnapshot()
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;
}
Änderungen, die über die Seite Firestore-Datenbank vorgenommen werden, werden jetzt in Echtzeit in der Webanwendung angezeigt.
- Erstellen Sie einen Commit mit der Commit-Nachricht „Für Echtzeitaktualisierungen von Restaurants sorgen“ und pushen Sie ihn in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Wählen Sie in der Webanwendung > Beispielrestaurants hinzufügen aus. Wenn die Snapshot-Funktion richtig implementiert ist, werden die Restaurants ohne Aktualisierung der Seite in Echtzeit angezeigt.
8. Von Nutzern eingereichte Rezensionen aus der Webanwendung speichern
- Ersetzen Sie in der Datei
src/lib/firebase/firestore.js
die FunktionupdateWithRating()
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()),
});
};
Mit diesem Code wird ein neues Firestore-Dokument eingefügt, das die neue Rezension darstellt. Außerdem aktualisiert der Code das vorhandene Firestore-Dokument, das das Restaurant darstellt, mit aktualisierten Zahlen für die Anzahl der Bewertungen und die durchschnittlich berechnete Bewertung.
- Ersetzen Sie die Funktion
addReviewToRestaurant()
durch den folgenden Code:
export async function addReviewToRestaurant(db, restaurantId, review) {
if (!restaurantId) {
throw new Error("No restaurant ID has been 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`)
);
// corrected line
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;
}
}
Next.js-Serveraktion implementieren
Eine Next.js-Serveraktion bietet eine praktische API für den Zugriff auf Formulardaten, z. B. data.get("text")
, um den Textwert aus der Formulareinreichungsnutzlast abzurufen.
So verwenden Sie eine Next.js-Serveraktion zum Senden des Überprüfungsformulars:
- Suchen Sie in der Datei
src/components/ReviewDialog.jsx
im Element<form>
nach dem Attributaction
.
<form action={handleReviewFormSubmission}>
Der action
-Attributwert bezieht sich auf eine Funktion, die Sie im nächsten Schritt implementieren.
- Ersetzen Sie in der Datei
src/app/actions.js
die FunktionhandleReviewFormSubmission()
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"),
});
}
Rezensionen für ein Restaurant hinzufügen
Sie haben die Unterstützung für das Einreichen von Rezensionen implementiert und können jetzt prüfen, ob Ihre Rezensionen korrekt in Cloud Firestore eingefügt werden.
So fügen Sie eine Rezension hinzu und prüfen, ob sie in Cloud Firestore eingefügt wurde:
- Erstellen Sie einen Commit mit der Commit-Nachricht „Nutzern erlauben, Restaurantbewertungen zu senden“ und übertragen Sie sie per Push in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App-Hosting und warten Sie, bis die neue Bereitstellung abgeschlossen ist.
- Aktualisieren Sie die Webanwendung und wählen Sie auf der Startseite ein Restaurant aus.
- Klicken Sie auf der Seite des Restaurants auf .
- Wählen Sie eine Bewertung aus.
- Rezension schreiben.
- Klicken Sie auf Senden. Ihre Rezension wird oben in der Liste der Rezensionen angezeigt.
- Suchen Sie in Cloud Firestore im Bereich Dokument hinzufügen nach dem Dokument des Restaurants, das Sie bewertet haben, und wählen Sie es aus.
- Wählen Sie im Bereich Sammlung starten die Option Bewertungen aus.
- Suchen Sie im Bereich Dokument hinzufügen nach dem Dokument, um zu prüfen, ob es wie erwartet eingefügt wurde.
9. Von Nutzern hochgeladene Dateien aus der Web-App speichern
In diesem Abschnitt fügen Sie eine Funktion hinzu, mit der 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.
So speichern Sie von Nutzern hochgeladene Dateien aus der Web-App:
- Sehen Sie sich in der Datei
src/components/Restaurant.jsx
den Code an, der ausgeführt wird, wenn der Nutzer 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. Sie implementieren jedoch das Verhalten der updateRestaurantImage()
-Funktion in den folgenden Schritten.
- Ersetzen Sie in der Datei
src/lib/firebase/storage.js
die FunktionenupdateRestaurantImage()
unduploadImage()
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.
Funktion zum Hochladen von Bildern prüfen
So überprüfen Sie, ob das Bild wie erwartet hochgeladen wird:
- Erstellen Sie einen Commit mit der Commit-Nachricht „Nutzer dürfen das Foto jedes Restaurants ändern“ und übertragen Sie ihn in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Prüfen Sie in der Web-App, ob Sie angemeldet sind, und wählen Sie ein Restaurant aus.
- Klicken Sie auf und laden Sie ein Bild aus Ihrem Dateisystem hoch. Das Image verlässt Ihre lokale Umgebung und wird in Cloud Storage hochgeladen. Das Bild wird sofort nach dem Hochladen angezeigt.
- Rufen Sie Cloud Storage for Firebase auf.
- Rufen Sie den Ordner auf, der das Restaurant darstellt. Das hochgeladene Bild ist im Ordner vorhanden.
10. Restaurantbewertungen mit generativer KI zusammenfassen
In diesem Abschnitt fügen Sie eine Funktion für Rezensionszusammenfassungen hinzu, damit Nutzer schnell sehen können, was andere von einem Restaurant halten, ohne jede Rezension lesen zu müssen.
Gemini API-Schlüssel in Cloud Secret Manager speichern
- Zur Verwendung der Gemini API benötigen Sie einen API-Schlüssel. Schlüssel in Google AI Studio erstellen
- App Hosting lässt sich in Cloud Secret Manager integrieren, damit Sie vertrauliche Werte wie API-Schlüssel sicher speichern können:
- Führen Sie in einem Terminal den Befehl aus, um ein neues Secret zu erstellen:
firebase apphosting:secrets:set gemini-api-key
- Wenn Sie zur Eingabe des Secret-Werts aufgefordert werden, kopieren Sie den Gemini API-Schlüssel aus Google AI Studio und fügen Sie ihn ein.
- Wenn Sie gefragt werden, ob das neue Secret zu
apphosting.yaml
hinzugefügt werden soll, geben SieY
ein, um zu bestätigen.
Ihr Gemini API-Schlüssel wird jetzt sicher in Cloud Secret Manager gespeichert und ist für Ihr App Hosting-Backend zugänglich.
Komponente „Rezensionszusammenfassung“ implementieren
- Ersetzen Sie in
src/components/Reviews/ReviewSummary.jsx
die FunktionGeminiSummary
durch den folgenden Code:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); const model = genAI.getGenerativeModel({ model: "gemini-pro"}); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map(review => review.text).join(reviewSeparator)} `; try { const result = await model.generateContent(prompt); const response = await result.response; const text = response.text(); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error contacting Gemini</p>; } }
- Erstellen Sie einen Commit mit der Commit-Nachricht „Use AI to summarize reviews“ und übertragen Sie ihn in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App Hosting und warten Sie, bis die neue Einführung abgeschlossen ist.
- Öffnen Sie eine Seite für ein Restaurant. Oben sollten Sie eine Zusammenfassung aller Rezensionen auf der Seite in einem Satz sehen.
- Fügen Sie eine neue Rezension hinzu und aktualisieren Sie die Seite. Die Zusammenfassung sollte sich ändern.
11. Fazit
Glückwunsch! Sie haben gelernt, wie Sie mit Firebase einer Next.js-App Funktionen hinzufügen. Dazu haben Sie Folgendes verwendet:
- Firebase App Hosting, um Ihren Next.js-Code bei jedem Push auf einen konfigurierten Branch automatisch zu erstellen und bereitzustellen.
- Firebase Authentication, um Funktionen zum An- und Abmelden zu aktivieren.
- Cloud Firestore für Restaurantdaten und Rezensionsdaten
- Cloud Storage for Firebase für Restaurantbilder