1. Hinweis
In diesem Codelab erfahren Sie, wie Sie Firebase in eine Next.js-Webanwendung namens Friendly Eats einbinden, 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.
- Anmelden und abmelden:In der fertigen Webanwendung können Sie sich mit Google anmelden und abmelden. Die Nutzeranmeldung und ‑speicherung 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. Rezensionsinformationen werden in Cloud Firestore gespeichert.
- Filter:In der fertigen Webanwendung 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 die 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
- Bilder in Cloud Storage for Firebase speichern
- Daten in einer Cloud Firestore-Datenbank lesen und schreiben
- Informationen zur Verwendung der Anmeldung über Google mit dem Firebase JavaScript SDK
Voraussetzungen
- Git
- Eine aktuelle stabile Version von Node.js
- Einen 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 den Code der App und verwendet die Firebase CLI.
GitHub-Repository erstellen
Den Codelab-Quellcode 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. Notieren Sie sich 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 mit einem 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
- Änderungen lokal mit Git nachverfolgen:
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.
- Kopieren Sie die neue URL, die GitHub für Sie erstellt. Sie sieht dann so aus:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.git
odergit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Führen Sie den folgenden Befehl aus, um lokale Änderungen in Ihr neues GitHub-Repository zu übertragen. Ersetzen Sie den Platzhalter
<REPOSITORY_URL>
durch die tatsächliche Repository-URL.git remote add origin <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 ob es sich um Version 13.9.0 oder höher handelt:
firebase --version
Wenn eine niedrigere Version angezeigt wird oder die 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 in Ihrem Browser Ihr Google-Konto aus und klicken Sie auf Zulassen.
3. Das Firebase-Projekt einrichten
In diesem Abschnitt richten Sie ein Firebase-Projekt ein und verknüpfen es mit einer 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. - Prüfen Sie im Modalfenster Firebase-Tarif bestätigen, ob der Tarif Blaze ist, 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 die Projekt-ID, da Sie sie später benötigen. Anhand dieser eindeutigen Kennung wird Ihr Projekt identifiziert, z. B. in der Firebase CLI.
Firebase-Tarif upgraden
Wenn Sie Firebase App Hosting und Cloud Storage for Firebase verwenden möchten, muss Ihr Firebase-Projekt den Blaze-Tarif (Pay-as-you-go) haben. Das bedeutet, dass es mit einem Cloud-Rechnungskonto verknüpft sein muss.
- Für ein Cloud-Rechnungskonto ist eine Zahlungsmethode wie eine Kreditkarte erforderlich.
- 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 den 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 Blaze-Tarif 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 zur 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 Web-Symbol 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
- Klicken Sie in der Firebase Console auf Authentifizierung.
- Klicken Sie auf Jetzt 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 Jetzt starten.
- Wählen Sie einen Speicherort für Ihren Standard-Storage-Bucket aus.
Für Buckets inUS-WEST1
,US-CENTRAL1
undUS-EAST1
kann die Stufe „Immer kostenlos“ für Google Cloud Storage genutzt werden. 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 Start-Codebasis 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 |
| Dienstfunktionen, die nicht unbedingt an React oder Next.js gebunden sind |
| Firebase-spezifischer Code und Firebase-Konfiguration |
| Statische Assets in der Webanwendung, z. B. Symbole |
| Routing mit dem Next.js App Router |
| API-Wege-Handler |
| Projektabhängigkeiten mit npm |
| Next.js-spezifische Konfiguration (Serveraktionen sind aktiviert) |
|
Server- und Clientkomponenten
Die App ist eine Next.js-Webanwendung, 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 gekennzeichnet ist.
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.
Mock-Daten
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
zusammengeführt.
5. App-Hosting-Backend erstellen
In diesem Abschnitt richten Sie ein App Hosting-Backend ein, um einen Branch 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 zum Bereitstellen dieser Sicherheitsregeln den folgenden Befehl in Ihrem Terminal aus:
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.
- Scrollen Sie nach unten zum Abschnitt Meine Apps und wählen Sie die Firebase-Webanwendung aus, die Sie zuvor in diesem Codelab erstellt haben.
- Kopieren Sie die Variable
firebaseConfig
und ihre Eigenschaften und Werte. - Öffnen Sie die Datei
apphosting.yaml
in Ihrem Code-Editor und füllen Sie die Werte der Umgebungsvariablen mit den Konfigurationswerten aus der Firebase Console aus. - 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 der Erstellung 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“ im Drop-down-Menü „Vorhandene Firebase-Web-App auswählen“ die Web-App aus, die Sie zuvor konfiguriert haben.
- Klicken Sie auf „Fertigstellen und bereitstellen“. Nach einem Moment werden Sie zu einer neuen Seite weitergeleitet, auf der Sie den Status Ihres neuen App-Hosting-Backends sehen.
- Klicken Sie nach Abschluss des Roll-outs unter „Domains“ auf Ihre kostenlose Domain. Aufgrund der DNS-Verbreitung kann es einige Minuten dauern, bis die Änderungen wirksam werden.
Sie haben die erste Webanwendung bereitgestellt. Jedes Mal, wenn Sie einen neuen Commit in den main
-Branch Ihres GitHub-Repositories pushen, wird in der Firebase Console ein neuer Build und ein neues Roll-out gestartet. Ihre Website wird automatisch aktualisiert, sobald das Roll-out abgeschlossen ist.
6. Authentifizierung zur 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 Authentifizierungsablauf. | |
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 Bereitstellung 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 den 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 <Header>
-Komponente 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 das Ergebnis zu überprüfen.
- 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 Bereitstellung abgeschlossen ist.
- Prüfen Sie das neue Authentifizierungsverhalten:
- Aktualisieren Sie die Webanwendung in Ihrem Browser. Ihr Anzeigename wird im Header angezeigt.
- Melden Sie sich ab und wieder an. Die Seite wird in Echtzeit aktualisiert, ohne dass sie neu geladen werden muss. Sie können diesen Schritt mit verschiedenen Nutzern wiederholen.
- Optional: Klicken Sie mit der rechten Maustaste auf die Webanwendung, wählen Sie Seitenquelltext anzeigen aus und suchen Sie nach dem Anzeigenamen. Sie wird in der Roh-HTML-Quelle angezeigt, die vom Server zurückgegeben wird.
7. Restaurantinformationen ansehen
Die Webanwendung enthält Mock-Daten für Restaurants und Rezensionen.
Mindestens ein Restaurant hinzufügen
So fügen Sie Ihrer lokalen Cloud Firestore-Datenbank Mock-Restaurantdaten hinzu:
- 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 in der Next.js-Web-App 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 Bereitstellung 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
Wenn Sie das Next.js-Framework verwenden, ist möglicherweise nicht klar, ob Daten zur Laufzeit auf dem Server oder clientseitig geladen werden.
So prüfen Sie, ob Restauranteinträge zur Laufzeit des Servers 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 animiert.
- Aktivieren Sie JavaScript in den Entwicklertools wieder.
Mit Cloud Firestore-Snapshot-Listenern auf Restaurantaktualisierungen 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 src/components/RestaurantListings.jsx
-Datei für die Hydratisierung serverseitig gerenderten Markups:
- Sehen Sie sich in der Datei
src/components/RestaurantListings.jsx
den folgenden Code an, 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 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 Bereitstellung 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, um die Einreichung des Formulars zur Überprüfung zu verarbeiten:
- 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 die Einreichung von Rezensionen implementiert. Jetzt können Sie 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 „Nutzer dürfen Restaurantbewertungen einreichen“ und pushen Sie ihn 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 von Ihnen rezensierten Restaurants 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 Webanwendung 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 Webanwendung:
- 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 das Verhalten der updateRestaurantImage()
-Funktion jedoch 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 updateRestaurantImageReference()
-Funktion ist bereits für Sie implementiert. Mit dieser Funktion wird ein vorhandenes Restaurantdokument in Cloud Firestore mit einer aktualisierten Bild-URL aktualisiert.
Funktion zum Hochladen von Bildern prüfen
So prü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 Bereitstellung 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 Bild verlässt Ihre lokale Umgebung und wird in Cloud Storage hochgeladen. Das Bild wird sofort nach dem Upload angezeigt.
- Rufen Sie Cloud Storage for Firebase auf.
- Rufen Sie den Ordner auf, der das Restaurant darstellt. Das von Ihnen 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. Erstellen Sie einen Schlüssel in Google AI Studio.
- 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 folgenden Befehl aus, um ein neues Secret zu erstellen:
firebase apphosting:secrets:set gemini-api-key
- Wenn Sie nach dem Secret-Wert gefragt werden, kopieren Sie Ihren 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 „Mit KI Rezensionen zusammenfassen“ und übertragen Sie ihn in Ihr GitHub-Repository.
- Öffnen Sie in der Firebase Console die Seite App-Hosting und warten Sie, bis die neue Bereitstellung abgeschlossen ist.
- Öffnen Sie eine Seite für ein Restaurant. Oben sollte eine Zusammenfassung aller Rezensionen auf der Seite in einem Satz angezeigt werden.
- 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 die Anmelde- und Abmeldefunktion zu aktivieren.
- Cloud Firestore für Restaurantdaten und Rezensionsdaten
- Cloud Storage for Firebase für Restaurantbilder