1. Zanim zaczniesz
Z tego ćwiczenia dowiesz się, jak zintegrować Firebase z aplikacją internetową Next.js o nazwie Friendly Eats, która jest witryną z opiniami o restauracjach.

Gotowa aplikacja internetowa oferuje przydatne funkcje, które pokazują, jak Firebase może pomóc w tworzeniu aplikacji Next.js. Do tych funkcji należą:
- Automatyczne kompilowanie i wdrażanie: w tym ćwiczeniu używamy Firebase App Hosting do automatycznego kompilowania i wdrażania kodu Next.js za każdym razem, gdy przesyłasz go do skonfigurowanej gałęzi.
- Logowanie i wylogowywanie: gotowa aplikacja internetowa umożliwia logowanie się przez Google i wylogowywanie się. Logowanie użytkowników i trwałość są zarządzane w całości przez Uwierzytelnianie Firebase.
- Obrazy: gotowa aplikacja internetowa umożliwia zalogowanym użytkownikom przesyłanie zdjęć restauracji. Komponenty z obrazem są przechowywane w Cloud Storage dla Firebase. Pakiet Firebase JavaScript SDK udostępnia publiczny adres URL przesłanych obrazów. Ten publiczny adres URL jest następnie przechowywany w odpowiednim dokumencie restauracji w Cloud Firestore.
- Opinie: gotowa aplikacja internetowa umożliwia zalogowanym użytkownikom publikowanie opinii o restauracjach, które składają się z oceny w gwiazdkach i wiadomości tekstowej. Informacje o opiniach są przechowywane w Cloud Firestore.
- Filtry: gotowa aplikacja internetowa umożliwia zalogowanym użytkownikom filtrowanie listy restauracji według kategorii, lokalizacji i ceny. Możesz też dostosować metodę sortowania. Dane są pobierane z Cloud Firestore, a zapytania Firestore są stosowane na podstawie użytych filtrów.
Wymagania wstępne
- konto GitHub,
- Znajomość Next.js i JavaScriptu
Czego się nauczysz
- jak używać Firebase z App Router Next.js i renderowaniem po stronie serwera;
- jak przechowywać obrazy w Cloud Storage dla Firebase,
- Jak odczytywać i zapisywać dane w bazie danych Cloud Firestore.
- Jak korzystać z funkcji Zaloguj się przez Google za pomocą pakietu Firebase JavaScript SDK.
Czego potrzebujesz
- Git
- najnowszą stabilną wersję Node.js,
- wybraną przeglądarkę, np. Google Chrome;
- środowisko programistyczne z edytorem kodu i terminalem,
- konto Google do tworzenia projektu w Firebase i zarządzania nim;
- Możliwość przejścia na abonament Blaze w projekcie w Firebase.
2. Konfigurowanie środowiska programistycznego i repozytorium GitHub
To ćwiczenie zawiera początkową bazę kodu aplikacji i korzysta z interfejsu wiersza poleceń Firebase.
Tworzenie repozytorium GitHub
Kod źródłowy ćwiczeń z programowania znajdziesz na stronie https://github.com/firebase/friendlyeats-web. Repozytorium zawiera przykładowe projekty dla wielu platform. W tym ćwiczeniu używamy jednak tylko katalogu nextjs-start. Zwróć uwagę na te katalogi:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Skopiuj folder nextjs-start do własnego repozytorium:
- W terminalu utwórz nowy folder na komputerze i przejdź do nowego katalogu:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web - Użyj pakietu npm giget, aby pobrać tylko folder
nextjs-start:npx giget@latest "gh:firebase/friendlyeats-web/nextjs-start#master" . --install - Śledź zmiany lokalnie za pomocą Gita:
git init git add . git commit -m "Codelab starting point" git branch -M main - Utwórz nowe repozytorium GitHub: https://github.com/new. Możesz nadać mu dowolną nazwę.
- W zależności od tego, jak uwierzytelniasz się w GitHubie (HTTPS lub SSH), skopiuj nowy adres URL utworzony przez GitHuba:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.gitlubgit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Prześlij zmiany lokalne do nowego repozytorium GitHub, uruchamiając to polecenie. Zastąp obiekt zastępczy
<REPOSITORY_URL>rzeczywistym adresem URL repozytorium.git remote add origin <REPOSITORY_URL> git push -u origin main - W repozytorium GitHub powinien pojawić się kod startowy.
Instalowanie i aktualizowanie interfejsu wiersza poleceń Firebase
Uruchom to polecenie, aby sprawdzić, czy masz zainstalowany interfejs wiersza poleceń Firebase w wersji 14.1.0 lub nowszej:
firebase --version
Jeśli widzisz starszą wersję lub nie masz zainstalowanego wiersza poleceń Firebase, uruchom polecenie instalacji:
npm install -g firebase-tools@latest
Jeśli nie możesz zainstalować interfejsu wiersza poleceń Firebase z powodu błędów uprawnień, zapoznaj się z dokumentacją npm lub użyj innej opcji instalacji.
Zaloguj się w Firebase.
- Uruchom to polecenie, aby zalogować się w interfejsie wiersza poleceń Firebase:
firebase login
- W zależności od tego, czy chcesz, aby Firebase zbierał dane, wpisz
YlubN. - W przeglądarce wybierz swoje konto Google, a następnie kliknij Zezwól.
3. Konfigurowanie projektu w Firebase
W tej sekcji skonfigurujesz projekt w Firebase i powiążesz z nim aplikację internetową Firebase. Skonfigurujesz też usługi Firebase używane przez przykładową aplikację internetową.
Tworzenie projektu w Firebase
- Zaloguj się w konsoli Firebase, używając tego samego konta Google co w poprzednim kroku.
- Kliknij przycisk, aby utworzyć nowy projekt, a następnie wpisz jego nazwę (np.
FriendlyEats Codelab).
- Kliknij Dalej.
- Jeśli pojawi się taka prośba, przeczytaj i zaakceptuj Warunki korzystania z Firebase, a następnie kliknij Dalej.
- (Opcjonalnie) Włącz pomoc AI w konsoli Firebase (funkcja „Gemini w Firebase”).
- W tym ćwiczeniu nie potrzebujesz Google Analytics, więc wyłącz tę opcję.
- Kliknij Utwórz projekt, poczekaj na udostępnienie projektu, a następnie kliknij Dalej.
Przejście na wyższy abonament Firebase
Aby korzystać z Firebase App Hosting i Cloud Storage dla Firebase, projekt Firebase musi być objęty abonamentem Blaze (płatność według wykorzystania), co oznacza, że jest on połączony z kontem rozliczeniowym Cloud.
- Konto rozliczeniowe Cloud wymaga formy płatności, np. karty kredytowej.
- Jeśli dopiero zaczynasz korzystać z Firebase i Google Cloud, sprawdź, czy kwalifikujesz się do otrzymania 300 USD środków i konta rozliczeniowego Cloud w bezpłatnym okresie próbnym.
- Jeśli wykonujesz ten ćwiczenie w ramach wydarzenia, zapytaj organizatora, czy są dostępne środki na Cloud.
Aby przejść na abonament Blaze, wykonaj te czynności:
- W konsoli Firebase wybierz opcję przejścia na wyższy abonament.
- Wybierz abonament Blaze. Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie, aby połączyć konto rozliczeniowe Cloud z projektem.
Jeśli w ramach tego uaktualnienia konieczne było utworzenie konta rozliczeniowego Cloud, może być konieczne powrócenie do procesu uaktualniania w konsoli Firebase, aby dokończyć uaktualnianie.
Dodawanie aplikacji internetowej do projektu w Firebase
- W projekcie w Firebase otwórz Przegląd projektu, kliknij Dodaj aplikację, a następnie Sieć.
- W polu tekstowym Nazwa aplikacji wpisz łatwą do zapamiętania nazwę aplikacji, np.
My Next.js app. - Nie zaznaczaj pola wyboru Skonfiguruj też Hosting Firebase dla tej aplikacji.
- Kliknij Zarejestruj aplikację > Przejdź do konsoli.
Konfigurowanie usług Firebase w konsoli Firebase
Konfigurowanie uwierzytelniania
- W panelu po lewej stronie konsoli Firebase rozwiń Build (Kompilacja), a następnie wybierz Authentication (Uwierzytelnianie).
- Kliknij Rozpocznij.
- W kolumnie Dostawcy logowania kliknij Google > Włącz.
- W polu tekstowym Publiczna nazwa projektu wpisz łatwą do zapamiętania nazwę, np.
My Next.js app. - Z menu Adres e-mail pomocy dla projektu wybierz swój adres e-mail.
- Kliknij Zapisz.
Konfigurowanie Cloud Firestore
- W lewym panelu konsoli Firebase rozwiń Kompilacja, a następnie wybierz Baza danych Firestore.
- Kliknij Utwórz bazę danych.
- Wybierz Wersja standardowa i kliknij Dalej.
- Nie zmieniaj identyfikatora bazy danych, pozostaw wartość
(default). - Wybierz lokalizację bazy danych, a następnie kliknij Dalej.
W przypadku prawdziwej aplikacji wybierz lokalizację, która jest blisko użytkowników. - Kliknij Uruchom w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł zabezpieczeń.
W dalszej części tego ćwiczenia dodasz reguły zabezpieczeń, aby chronić swoje dane. Nie rozpowszechniaj ani nie udostępniaj publicznie aplikacji bez dodania reguł zabezpieczeń do bazy danych. - Kliknij Utwórz.
Konfigurowanie Cloud Storage dla Firebase
- W lewym panelu konsoli Firebase rozwiń Kompilacja, a następnie wybierz Miejsce na dane.
- Kliknij Rozpocznij.
- Wybierz lokalizację domyślnego zasobnika Storage.
Zasobniki w regionachUS-WEST1,US-CENTRAL1iUS-EAST1mogą korzystać z poziomu „Zawsze bezpłatnie” w Google Cloud Storage. Zasobniki we wszystkich innych lokalizacjach podlegają cenom i zasadom korzystania z Google Cloud Storage. - Kliknij Uruchom w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł zabezpieczeń.
W dalszej części tego ćwiczenia dodasz reguły zabezpieczeń, aby chronić swoje dane. Nie rozpowszechniaj ani nie udostępniaj publicznie aplikacji bez dodania reguł zabezpieczeń do zasobnika Storage. - Kliknij Utwórz.
Wdrażanie reguł zabezpieczeń
Kod zawiera już zestawy reguł zabezpieczeń dla Firestore i Cloud Storage dla Firebase. Po wdrożeniu reguł zabezpieczeń dane w bazie danych i zasobniku są lepiej chronione przed nadużyciami.
- W terminalu skonfiguruj interfejs wiersza poleceń, aby używał utworzonego wcześniej projektu w Firebase:
Gdy pojawi się prośba o alias, wpiszfirebase use --add
friendlyeats-codelab. - Aby wdrożyć te reguły zabezpieczeń (oraz indeksy, które będą potrzebne później), uruchom w terminalu to polecenie:
firebase deploy --only firestore,storage
- Jeśli pojawi się pytanie:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", naciśnijEnter, aby wybrać Tak.
4. Przeglądanie początkowej bazy kodu
W tej sekcji omówimy kilka obszarów początkowej bazy kodu aplikacji, do których dodasz funkcje w tym ćwiczeniu.
Struktura folderów i plików
Tabela poniżej zawiera przegląd struktury folderów i plików aplikacji:
Foldery i pliki | Opis |
| komponenty React do filtrów, nagłówków, szczegółów restauracji i opinii; |
| funkcje użytkowe, które niekoniecznie są powiązane z Reactem lub Next.js; |
| Kod Firebase i konfiguracja Firebase |
| zasoby statyczne w aplikacji internetowej, np. ikony; |
| Routing za pomocą routera aplikacji Next.js |
| Zależności projektu z npm |
| Konfiguracja Next.js (działania serwera są włączone) |
| Konfiguracja usługi językowej JavaScript |
Komponenty serwera i klienta
Aplikacja internetowa Next.js korzysta z App Router. W całej aplikacji używane jest renderowanie po stronie serwera. Na przykład plik src/app/page.js to komponent serwera odpowiedzialny za stronę główną. Plik src/components/RestaurantListings.jsx to komponent klienta oznaczony dyrektywą "use client" na początku pliku.
Instrukcje importu
Możesz zauważyć instrukcje importu podobne do tych:
import RatingPicker from "@/src/components/RatingPicker.jsx";
Aplikacja używa symbolu @, aby uniknąć nieporęcznych względnych ścieżek importu, co jest możliwe dzięki aliasom ścieżek.
Interfejsy API Firebase
Cały kod interfejsu Firebase API jest opakowany w katalogu src/lib/firebase. Poszczególne komponenty React importują następnie opakowane funkcje z katalogu src/lib/firebase, zamiast importować funkcje Firebase bezpośrednio.
Dane próbne
Przykładowe dane dotyczące restauracji i opinii znajdują się w pliku src/lib/randomData.js. Dane z tego pliku są składane w kodzie w pliku src/lib/fakeRestaurants.js.
5. Tworzenie backendu App Hosting
W tej sekcji skonfigurujesz backend App Hosting, aby obserwować gałąź w repozytorium Git.
Po ukończeniu tej sekcji będziesz mieć backend App Hosting połączony z repozytorium na GitHubie, który będzie automatycznie ponownie kompilować i wdrażać nową wersję aplikacji za każdym razem, gdy prześlesz nowe zatwierdzenie do gałęzi main.
Utworzenie backendu
- W konsoli Firebase otwórz stronę App Hosting.
- Kliknij Rozpocznij, aby rozpocząć proces tworzenia backendu.
- Wybierz region. W przypadku prawdziwej aplikacji wybierz region najbliżej użytkowników.
- Aby skonfigurować uwierzytelnianie GitHub, postępuj zgodnie z instrukcjami w kroku Importowanie repozytorium GitHub.
- W sekcji Repozytorium wybierz Przyznaj dostęp do nowego repozytorium w GitHubie i postępuj zgodnie z instrukcjami, aby włączyć dostęp do utworzonego wcześniej repozytorium GitHub.
- Kliknij Odśwież listę, aby odświeżyć listę, a następnie wybierz repozytorium i kliknij Dalej.
- Skonfiguruj ustawienia wdrażania:
- Ustaw aktywną gałąź na
main. - Pozostaw katalog główny jako
/. - Włącz automatyczne wdrażanie.
- Ustaw aktywną gałąź na
- Nazwij backend
friendlyeats-codelabi kliknij Dalej. - W sekcji Powiąż aplikację internetową Firebase wybierz Wybierz istniejącą aplikację internetową Firebase i wybierz dodaną aplikację z listy.
- Kliknij Zakończ i wdróż. Nastąpi przekierowanie na nową stronę, na której możesz zobaczyć stan nowego backendu App Hosting.
- Kliknij Wyświetl, aby zobaczyć więcej informacji o wdrożeniu App Hosting, w tym stan wdrażania, logi i szczegóły dotyczące wykorzystania.
- Po zakończeniu wdrażania kliknij, aby otworzyć adres URL witryny w sekcji Domeny. Zanim zacznie działać, może minąć kilka minut ze względu na propagację DNS.
- Ojej. Gdy strona się wczyta, zobaczysz komunikat o błędzie „Błąd aplikacji: wystąpił wyjątek po stronie serwera (więcej informacji znajdziesz w logach serwera)”.
- W konsoli Firebase sprawdź kartę Logi backendu App Hosting. Zobaczysz dziennik „Błąd: nie zaimplementowano”. Naprawimy to w następnym kroku, gdy dodamy uwierzytelnianie.
Udało Ci się wdrożyć początkową aplikację internetową. Za każdym razem, gdy przeniesiesz nowe zatwierdzenie do gałęzi main repozytorium GitHub, w konsoli Firebase rozpocznie się nowa kompilacja i wdrożenie, a po zakończeniu wdrażania witryna zostanie automatycznie zaktualizowana.
6. Dodawanie uwierzytelniania do aplikacji internetowej
W tej sekcji dodasz uwierzytelnianie do aplikacji internetowej, aby móc się do niej zalogować.
Dodaj autoryzowaną domenę
Uwierzytelnianie Firebase będzie akceptować tylko żądania logowania z domen, na które zezwolisz. W tym miejscu dodamy domenę backendu App Hosting do listy zatwierdzonych domen w projekcie.
- Otwórz stronę App Hosting i kliknij Wyświetl pod wdrożoną witryną, aby otworzyć stronę Przegląd. Skopiuj nazwę domeny backendu App Hosting.
- Otwórz kartę Ustawienia uwierzytelniania i wybierz projekt, do którego chcesz dodać autoryzowaną domenę. Następnie znajdź sekcję Autoryzowane domeny i kliknij ją.
- Kliknij przycisk Dodaj domenę.
- Wpisz domenę backendu App Hosting.
- Kliknij Dodaj.
Wdrażanie funkcji logowania i wylogowywania
W pliku src/lib/firebase/auth.js zastąp funkcje onAuthStateChanged, onIdTokenChanged, signInWithGoogle i signOut tym kodem:
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export function onIdTokenChanged(cb) {
return _onIdTokenChanged(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);
}
}
Ten kod używa tych interfejsów Firebase API:
Interfejs API Firebase | Opis |
Dodaje obserwatora zmian stanu logowania użytkownika. | |
Dodaje obserwatora zmian w tokenie identyfikacji użytkownika. | |
Tworzy instancję dostawcy uwierzytelniania Google. | |
Rozpoczyna proces uwierzytelniania oparty na oknie. | |
Wylogowuje użytkownika. |
W pliku src/components/Header.jsx kod wywołuje już funkcje signInWithGoogle i signOut.
Wysyłanie stanu uwierzytelniania do serwera
Aby przekazać stan uwierzytelniania do serwera, użyjemy plików cookie. Za każdym razem, gdy stan uwierzytelniania zmieni się w kliencie, zaktualizujemy plik cookie __session.
W pliku src/components/Header.jsx zastąp funkcję useUserSession tym kodem:
function useUserSession(initialUser) {
useEffect(() => {
return onIdTokenChanged(async (user) => {
if (user) {
const idToken = await user.getIdToken();
await setCookie("__session", idToken);
} else {
await deleteCookie("__session");
}
if (initialUser?.uid === user?.uid) {
return;
}
window.location.reload();
});
}, [initialUser]);
return initialUser;
}
Odczytywanie stanu uwierzytelniania na serwerze
Użyjemy FirebaseServerApp, aby odzwierciedlić stan uwierzytelniania klienta na serwerze.
Otwórz src/lib/firebase/serverApp.js i zastąp funkcję getAuthenticatedAppForUser:
export async function getAuthenticatedAppForUser() {
const authIdToken = (await cookies()).get("__session")?.value;
// Firebase Server App is a new feature in the JS SDK that allows you to
// instantiate the SDK with credentials retrieved from the client & has
// other affordances for use in server environments.
const firebaseServerApp = initializeServerApp(
// https://github.com/firebase/firebase-js-sdk/issues/8863#issuecomment-2751401913
initializeApp(),
{
authIdToken,
}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
Zweryfikuj zmiany
Układ główny w pliku src/app/layout.js renderuje nagłówek i przekazuje użytkownika (jeśli jest dostępny) jako właściwość.
<Header initialUser={currentUser?.toJSON()} />
Oznacza to, że komponent <Header> renderuje dane użytkownika, jeśli są dostępne, podczas działania serwera. Jeśli po początkowym wczytaniu strony w trakcie jej cyklu życia nastąpią jakieś aktualizacje uwierzytelniania, zostaną one obsłużone przez moduł obsługi onAuthStateChanged.
Teraz nadszedł czas na wdrożenie nowej kompilacji i sprawdzenie, co udało się stworzyć.
- Utwórz zatwierdzenie z komunikatem „Add authentication” i prześlij je do repozytorium GitHub.
git add . git commit -m "Add authentication" git push - Otwórz stronę App Hosting i po zakończeniu nowego wdrożenia kliknij adres URL witryny, aby ją otworzyć.
- Testowanie uwierzytelniania:
- Zaloguj się na konto Google i sprawdź, czy po zalogowaniu się w nagłówku wyświetla się Twoja wyświetlana nazwa.
- Wyloguj się i zaloguj jeszcze raz. Możesz powtórzyć ten krok z innymi użytkownikami.
- Opcjonalnie: kliknij prawym przyciskiem myszy aplikację internetową, wybierz Wyświetl źródło strony i wyszukaj wyświetlaną nazwę. Znajduje się w nieprzetworzonym źródle HTML zwróconym z serwera.
7. Wyświetlanie informacji o restauracji
Aplikacja internetowa zawiera przykładowe dane dotyczące restauracji i opinii.
Dodaj co najmniej 1 restaurację
Aby wstawić przykładowe dane restauracji do lokalnej bazy danych Cloud Firestore, wykonaj te czynności:
- Zaloguj się w aplikacji internetowej, jeśli jeszcze nie masz konta. Następnie kliknij
> Dodaj przykładowe restauracje. Zauważ, że w aplikacji internetowej Friendly Eats nie wyświetlają się żadne restauracje, ponieważ nie skonfigurowaliśmy jeszcze kodu pobierania danych. Naprawimy to w następnym kroku. - W konsoli Firebase na stronie Baza danych Firestore wybierz restauracje. Zobaczysz dokumenty najwyższego poziomu w kolekcji restauracji, z których każdy reprezentuje restaurację.
- Kliknij kilka dokumentów, aby zapoznać się z właściwościami dokumentu restauracji.
Wyświetl listę restauracji
Baza danych Cloud Firestore zawiera teraz restauracje, które aplikacja internetowa Next.js może wyświetlać.
Aby zdefiniować kod pobierania danych, wykonaj te czynności:
- W pliku
src/app/page.jsznajdź komponent serwera<Home />i sprawdź wywołanie funkcjigetRestaurants, która pobiera listę restauracji w czasie działania serwera. W kolejnych krokach zaimplementujesz funkcjęgetRestaurants. - W pliku
src/lib/firebase/firestore.jszastąp funkcjeapplyQueryFiltersigetRestaurantstym kodem:
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(),
};
});
}
- Utwórz zatwierdzenie z komunikatem „Read the list of restaurants from Firestore” (Odczytaj listę restauracji z Firestore) i prześlij je do repozytorium GitHub.
git add . git commit -m "Read the list of restaurants from Firestore" git push - Otwórz stronę App Hosting w konsoli Firebase i poczekaj na zakończenie nowego wdrożenia.
- Odśwież stronę w aplikacji internetowej. Zdjęcia restauracji wyświetlają się na stronie jako kafelki.
Sprawdzanie, czy informacje o restauracjach wczytują się w czasie działania serwera
W przypadku platformy Next.js może nie być oczywiste, kiedy dane są wczytywane w czasie działania serwera, a kiedy w czasie działania po stronie klienta.
Aby sprawdzić, czy informacje o restauracjach są wczytywane w czasie działania serwera, wykonaj te czynności:
- W aplikacji internetowej otwórz Narzędzia deweloperskie i wyłącz JavaScript.

- Odśwież aplikację internetową. Lista restauracji nadal się wczytuje. Informacje o restauracji są zwracane w odpowiedzi serwera. Gdy JavaScript jest włączony, informacje o restauracji są pobierane za pomocą kodu JavaScript po stronie klienta.
- W Narzędziach deweloperskich ponownie włącz JavaScript.
Nasłuchiwanie aktualizacji restauracji za pomocą detektorów zrzutów Cloud Firestore
W poprzedniej sekcji pokazaliśmy, jak początkowy zestaw restauracji został wczytany z pliku src/app/page.js. Plik src/app/page.js jest komponentem serwera i jest renderowany na serwerze, w tym kodzie Firebase do pobierania danych.
Plik src/components/RestaurantListings.jsx jest komponentem klienta i można go skonfigurować tak, aby nawadniał znaczniki renderowane przez serwer.
Aby skonfigurować plik src/components/RestaurantListings.jsx do hydratacji znaczników renderowanych po stronie serwera, wykonaj te czynności:
- W pliku
src/components/RestaurantListings.jsxznajdziesz ten kod, który został już napisany:
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [filters]);
Ten kod wywołuje funkcję getRestaurantsSnapshot(), która jest podobna do funkcji getRestaurants() zaimplementowanej w poprzednim kroku. Ta funkcja zrzutu udostępnia jednak mechanizm wywołania zwrotnego, dzięki czemu wywołanie zwrotne jest wywoływane za każdym razem, gdy w kolekcji restauracji zostanie wprowadzona zmiana.
- W pliku
src/lib/firebase/firestore.jszastąp funkcjęgetRestaurantsSnapshot()tym kodem:
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);
return 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);
});
}
- W pliku
src/lib/firebase/firestore.jszastąp funkcjęgetRestaurantSnapshotById()tym kodem:
export function getRestaurantSnapshotById(restaurantId, cb) {
if (!restaurantId) {
console.log("Error: Invalid ID received: ", restaurantId);
return;
}
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
const docRef = doc(db, "restaurants", restaurantId);
return onSnapshot(docRef, (docSnap) => {
cb({
...docSnap.data(),
timestamp: docSnap.data().timestamp.toDate(),
});
});
}
Zmiany wprowadzone na stronie Baza danych Firestore są teraz odzwierciedlane w aplikacji internetowej w czasie rzeczywistym.
- Utwórz zatwierdzenie z komunikatem „Listen for realtime restaurant updates” i prześlij je do repozytorium GitHub.
git add . git commit -m "Listen for realtime restaurant updates" git push - Otwórz stronę App Hosting w konsoli Firebase i poczekaj na zakończenie nowego wdrożenia.
- W aplikacji internetowej kliknij
> Dodaj przykładowe restauracje. Jeśli funkcja migawki jest prawidłowo zaimplementowana, restauracje pojawiają się w czasie rzeczywistym bez odświeżania strony.
8. Zapisywanie opinii przesłanych przez użytkowników z aplikacji internetowej
- W pliku
src/lib/firebase/firestore.jszastąp funkcjęupdateWithRating()tym kodem:
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()),
});
};
Ten kod wstawia nowy dokument Firestore reprezentujący nową opinię. Kod aktualizuje też istniejący dokument Firestore, który reprezentuje restaurację, o zaktualizowane dane dotyczące liczby ocen i obliczonej średniej oceny.
- Zastąp funkcję
addReviewToRestaurant()tym kodem:
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;
}
}
Implementowanie działania serwera Next.js
Działanie serwera Next.js udostępnia wygodny interfejs API do uzyskiwania dostępu do danych formularza, takich jak data.get("text"), aby pobrać wartość tekstową z ładunku przesłanego formularza.
Aby użyć akcji serwera Next.js do przetworzenia przesłanego formularza opinii, wykonaj te czynności:
- W pliku
src/components/ReviewDialog.jsxznajdź atrybutactionw elemencie<form>.
<form
action={handleReviewFormSubmission}
onSubmit={() => {
handleClose();
}}
>
Wartość atrybutu action odnosi się do funkcji, którą zaimplementujesz w następnym kroku.
- W pliku
src/app/actions.jszastąp funkcjęhandleReviewFormSubmission()tym kodem:
export async function handleReviewFormSubmission(data) {
const { firebaseServerApp } = await getAuthenticatedAppForUser();
const db = getFirestore(firebaseServerApp);
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"),
});
}
Dodawanie opinii o restauracji
Obsługa przesyłania opinii została wdrożona, więc teraz możesz sprawdzić, czy opinie są prawidłowo wstawiane do Cloud Firestore.
Aby dodać opinię i sprawdzić, czy została wstawiona do Cloud Firestore, wykonaj te czynności:
- Utwórz zatwierdzenie z komunikatem „Allow users to submit restaurant reviews” i prześlij je do repozytorium GitHub.
git add . git commit -m "Allow users to submit restaurant reviews" git push - Otwórz stronę App Hosting w konsoli Firebase i poczekaj na zakończenie nowego wdrożenia.
- Odśwież aplikację internetową i wybierz restaurację na stronie głównej.
- Na stronie restauracji kliknij
. - Wybierz liczbę gwiazdek.
- Napisz opinię.
- Kliknij Prześlij. Twoja opinia pojawi się u góry listy opinii.
- W Cloud Firestore wyszukaj w panelu Dodaj dokument dokument restauracji, którą oceniasz, i wybierz go.
- W panelu Rozpocznij zbieranie danych wybierz oceny.
- W panelu Dodaj dokument znajdź dokument do sprawdzenia, aby upewnić się, że został wstawiony zgodnie z oczekiwaniami.
9. Zapisywanie plików przesłanych przez użytkowników z aplikacji internetowej
W tej sekcji dodasz funkcję, która pozwoli Ci zastąpić obraz powiązany z restauracją, gdy się zalogujesz. Prześlesz obraz do Pamięci Firebase i zaktualizujesz adres URL obrazu w dokumencie Cloud Firestore, który reprezentuje restaurację.
Aby zapisać pliki przesłane przez użytkowników z aplikacji internetowej, wykonaj te czynności:
- W pliku
src/components/Restaurant.jsxsprawdź kod, który jest uruchamiany, gdy użytkownik przesyła plik:
async function handleRestaurantImage(target) {
const image = target.files ? target.files[0] : null;
if (!image) {
return;
}
const imageURL = await updateRestaurantImage(id, image);
setRestaurantDetails({ ...restaurantDetails, photo: imageURL });
}
Nie musisz wprowadzać żadnych zmian w tej funkcji, ale w kolejnych krokach zaimplementujesz działanie funkcji updateRestaurantImage().
- W pliku
src/lib/firebase/storage.jszastąp funkcjeupdateRestaurantImage()iuploadImage()tym kodem:
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);
}
Funkcja updateRestaurantImageReference() jest już dla Ciebie wdrożona. Ta funkcja aktualizuje istniejący dokument restauracji w Cloud Firestore, dodając zaktualizowany adres URL obrazu.
Sprawdzanie funkcji przesyłania obrazów
Aby sprawdzić, czy obraz został przesłany prawidłowo:
- Utwórz zatwierdzenie z komunikatem „Zezwalaj użytkownikom na zmianę zdjęcia każdej restauracji” i prześlij je do repozytorium GitHub.
git add . git commit -m "Allow users to change each restaurants' photo" git push - Otwórz stronę App Hosting w konsoli Firebase i poczekaj na zakończenie nowego wdrożenia.
- W aplikacji internetowej sprawdź, czy jesteś zalogowany(-a), i wybierz restaurację.
- Kliknij
i prześlij obraz z systemu plików. Obraz opuszcza środowisko lokalne i jest przesyłany do Cloud Storage. Obraz pojawi się natychmiast po przesłaniu. - Otwórz Cloud Storage dla Firebase.
- Przejdź do folderu, który reprezentuje restaurację. Przesłany obraz znajduje się w folderze.

10. Podsumowywanie opinii o restauracjach za pomocą generatywnej AI
W tej sekcji dodasz funkcję podsumowania opinii, dzięki której użytkownik będzie mógł szybko dowiedzieć się, co inni myślą o restauracji, bez konieczności czytania każdej opinii.
Przechowywanie klucza interfejsu Gemini API w usłudze Cloud Secret Manager
- Aby korzystać z interfejsu Gemini API, potrzebujesz klucza interfejsu API. Otwórz Google AI Studio i kliknij Utwórz klucz interfejsu API.
- Nazwij klucz, jak chcesz. Jeśli Twojego projektu nie ma na liście Wybierz zaimportowany projekt, kliknij Importuj projekt, zaznacz projekt na liście i kliknij Importuj. Na koniec wybierz go w sekcji Wybierz zaimportowany projekt i kliknij Utwórz klucz.
- App Hosting integruje się z Cloud Secret Manager, aby umożliwić bezpieczne przechowywanie wartości poufnych, takich jak klucze interfejsu API:
- W terminalu uruchom polecenie, aby utworzyć nowy obiekt tajny:
firebase apphosting:secrets:set GEMINI_API_KEY- Gdy pojawi się prośba o podanie wartości obiektu tajnego, skopiuj i wklej klucz interfejsu Gemini API z Google AI Studio.
- Gdy pojawi się pytanie, czy nowy klucz tajny jest przeznaczony do środowiska produkcyjnego czy do testów lokalnych, wybierz „Produkcja”.
- Gdy pojawi się pytanie, czy chcesz przyznać dostęp, aby konto usługi backendu mogło uzyskać dostęp do obiektu tajnego, wybierz „Tak”.
- Gdy pojawi się pytanie, czy nowy obiekt tajny ma zostać dodany do
apphosting.yaml, wpiszY, aby zaakceptować.
Klucz interfejsu Gemini API jest teraz bezpiecznie przechowywany w usłudze Cloud Secret Manager i jest dostępny dla backendu App Hosting.
Implementowanie komponentu podsumowania opinii
- W pliku
src/components/Reviews/ReviewSummary.jsxzastąp funkcjęGeminiSummarytym kodem:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); 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 { if (!process.env.GEMINI_API_KEY) { // Make sure GEMINI_API_KEY environment variable is set: // https://genkit.dev/docs/get-started/ throw new Error( 'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"' ); } // Configure a Genkit instance. const ai = genkit({ plugins: [googleAI()], model: gemini20Flash, // set default model }); const { text } = await ai.generate(prompt); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error summarizing reviews.</p>; } } - Utwórz zatwierdzenie z komunikatem „Use AI to summarize reviews” (Użyj AI do podsumowywania opinii) i prześlij je do repozytorium GitHub.
git add . git commit -m "Use AI to summarize reviews" git push - Otwórz stronę App Hosting w konsoli Firebase i poczekaj na zakończenie nowego wdrożenia.
- Otwórz stronę restauracji. U góry powinno być widoczne jednozdaniowe podsumowanie wszystkich opinii na stronie.
- Dodaj nową opinię i odśwież stronę. Podsumowanie powinno się zmienić.
11. Cofanie publikacji witryny App Hosting
Jeśli po ukończeniu tego ćwiczenia nie zamierzasz dalej korzystać z aplikacji, możesz ją wycofać, aby nikt nie miał dostępu do Twoich zasobów Firestore, Storage i Gemini. W każdej chwili możesz ponownie opublikować stronę.
Aby cofnąć publikację witryny App Hosting:
- Otwórz App Hosting w konsoli Firebase.
- Znajdź backend aplikacji i kliknij Wyświetl.
- W sekcji Informacje o backendzie obok opcji Domeny kliknij Zarządzaj. Spowoduje to wczytanie strony Domeny.
- Obok domeny kliknij ikonę Więcej (3 pionowe kropki), wybierz Wyłącz domenę, a następnie kliknij Wyłącz, aby potwierdzić.
12. Podsumowanie
Gratulacje! Wiesz już, jak używać Firebase do dodawania funkcji do aplikacji Next.js. W szczególności udało Ci się:
- Firebase App Hosting, aby automatycznie kompilować i wdrażać kod Next.js za każdym razem, gdy przesyłasz go do skonfigurowanej gałęzi.
- Uwierzytelnianie Firebase, aby umożliwić logowanie się i wylogowywanie.
- Cloud Firestore do przechowywania danych o restauracjach i opinii o nich.
- Cloud Storage dla Firebase na zdjęcia restauracji.