1. Zanim zaczniesz
Z tego samouczka 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. Są to:
- Automatyczne kompilowanie i wdrażanie: w tym laboratorium wykorzystujemy Hosting aplikacji Firebase do automatycznego kompilowania i wdrażania kodu Next.js za każdym razem, gdy przenosisz zmiany do skonfigurowanej gałęzi.
- Logowanie i wylogowywanie: ukończona aplikacja internetowa umożliwia logowanie się przez Google i wylogowywanie. Logowanie użytkowników i utrzymywanie sesji jest w całości zarządzane przez Uwierzytelnianie Firebase.
- Obrazy: ukończona aplikacja internetowa umożliwia zalogowanym użytkownikom przesyłanie zdjęć restauracji. Pliki z obrazami 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: ukończona aplikacja internetowa umożliwia zalogowanym użytkownikom publikowanie opinii o restauracjach, które składają się z oceny w postaci gwiazdek i wiadomości tekstowej. Informacje o opiniach są przechowywane w Cloud Firestore.
- Filtry: ukończona aplikacja internetowa umożliwia zalogowanym użytkownikom filtrowanie listy restauracji na podstawie kategorii, lokalizacji i ceny. Możesz też dostosować używaną metodę sortowania. Dostęp do danych jest uzyskiwany 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 routerem aplikacji 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 w pakiecie Firebase JavaScript SDK.
Czego potrzebujesz
- Git
- Najnowsza stabilna wersja Node.js
- wybraną przeglądarkę, np. Google Chrome;
- Środowisko programistyczne z edytorem kodu i terminalem
- konto Google do tworzenia projektu Firebase i zarządzania nim;
- możliwość przejścia na abonament Blaze w projekcie Firebase;
2. Konfigurowanie środowiska programistycznego i repozytorium GitHub
W tym Codelabie znajdziesz początkowy kod aplikacji, który 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 na różne platformy. W tym laboratorium 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. Nadaj mu dowolną nazwę.
- Skopiuj nowy adres URL utworzony przez GitHub. Będzie on wyglądać mniej więcej tak:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.git
lubgit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Wypchnij lokalne zmiany do nowego repozytorium GitHub, wykonując to polecenie. Zastąp symbol 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 początkowy.
Instalowanie lub aktualizowanie wiersza poleceń Firebase
Uruchom to polecenie, aby sprawdzić, czy wiersz poleceń Firebase jest zainstalowany i czy ma wersję 14.1.0 lub nowszą:
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ć wiersza poleceń Firebase z powodu błędów uprawnień, zapoznaj się z dokumentacją npm lub skorzystaj z innej opcji instalacji.
Logowanie w Firebase
- Aby zalogować się w interfejsie wiersza poleceń Firebase, uruchom to polecenie:
firebase login
- Wpisz
Y
lubN
w zależności od tego, czy chcesz, aby Firebase zbierał dane. - W przeglądarce wybierz konto Google, a potem kliknij Zezwól.
3. Konfigurowanie projektu Firebase
W tej sekcji skonfigurujesz projekt Firebase i powiążesz z nim aplikację internetową Firebase. Skonfigurujesz też usługi Firebase używane przez przykładową aplikację internetową.
Tworzenie projektu Firebase
- Zaloguj się w konsoli Firebase za pomocą tego samego konta Google, którego używasz w poprzednim kroku.
- Kliknij przycisk, aby utworzyć nowy projekt, a potem wpisz jego nazwę (np.
FriendlyEats Codelab
).
- Kliknij Dalej.
- Po wyświetleniu monitu przeczytaj i zaakceptuj warunki usługi Firebase, a potem kliknij Dalej.
- (Opcjonalnie) Włącz w konsoli Firebase pomoc AI (nazywaną „Gemini w Firebase”).
- W tym samouczku nie potrzebujesz Google Analytics, więc wyłącz opcję Google Analytics.
- Kliknij Utwórz projekt, poczekaj, aż projekt zostanie udostępniony, a następnie kliknij Dalej.
Przejście na wyższy abonament Firebase
Aby korzystać z Hostingu aplikacji Firebase i Cloud Storage for Firebase, Twój projekt Firebase musi być objęty abonamentem Blaze (płatność według wykorzystania), co oznacza, że jest 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 możesz otrzymać środki w wysokości 300 USD i bezpłatne konto rozliczeniowe Cloud.
- Jeśli wykonujesz te ćwiczenia w ramach wydarzenia, zapytaj organizatora, czy są dostępne środki w Google Cloud.
Aby przenieść projekt na abonament Blaze:
- W konsoli Firebase wybierz przejście na wyższy abonament.
- Wybierz pakiet Blaze. Postępuj zgodnie z instrukcjami wyświetlanymi na ekranie, aby połączyć konto rozliczeniowe Cloud z projektem.
Jeśli w ramach tego przejścia na wyższy abonament konieczne było utworzenie konta rozliczeniowego Cloud, może być konieczne powrócenie do procesu przejścia na wyższy abonament w konsoli Firebase, aby go dokończyć.
Dodawanie aplikacji internetowej do projektu Firebase
- Otwórz Przegląd projektu w projekcie Firebase, a potem kliknij
Internet.
Jeśli w projekcie masz już zarejestrowane aplikacje, kliknij Dodaj aplikację, aby zobaczyć ikonę Internet. - W polu tekstowym Pseudonim aplikacji wpisz łatwy do zapamiętania pseudonim aplikacji, np.
My Next.js app
. - Pole wyboru Skonfiguruj też Hosting Firebase dla tej aplikacji pozostaw niezaznaczone.
- Kliknij Zarejestruj aplikację > Przejdź do konsoli.
Konfigurowanie usług Firebase w konsoli Firebase
Konfigurowanie uwierzytelniania
- W konsoli Firebase otwórz Uwierzytelnianie.
- Kliknij Rozpocznij.
- W kolumnie Dodatkowi dostawcy kliknij Google > Włącz.
- W polu tekstowym Nazwa projektu widoczna publicznie wpisz łatwą do zapamiętania nazwę, np.
My Next.js app
. - W menu Adres e-mail pomocy dotyczący projektu wybierz swój adres e-mail.
- Kliknij Zapisz.
Konfigurowanie Cloud Firestore
- W panelu po lewej stronie konsoli Firebase rozwiń Kompilacja, a następnie wybierz Baza danych Firestore.
- Kliknij Utwórz bazę danych.
- W polu Identyfikator bazy danych pozostaw wartość
(default)
. - Wybierz lokalizację bazy danych i 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ł bezpieczeństwa.
W dalszej części tego laboratorium dodasz reguły bezpieczeństwa, aby zabezpieczyć swoje dane. Nierozpowszechniajani nie udostępniaj publicznie aplikacji bez dodania reguł bezpieczeństwa do bazy danych. - Kliknij Utwórz.
Konfigurowanie Cloud Storage dla Firebase
- W panelu po lewej stronie konsoli Firebase rozwiń Kompilacja, a następnie wybierz Storage.
- Kliknij Rozpocznij.
- Wybierz lokalizację domyślnego zasobnika Storage.
Zasobniki w regionachUS-WEST1
,US-CENTRAL1
iUS-EAST1
mogą korzystać z poziomu „Zawsze bezpłatny” w Google Cloud Storage. W przypadku zasobników w innych lokalizacjach obowiązuje cennik i wykorzystanie Google Cloud Storage. - Kliknij Uruchom w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł bezpieczeństwa.
W dalszej części tego laboratorium dodasz reguły bezpieczeństwa, aby zabezpieczyć swoje dane. Nieudostępniaj aplikacji publicznie bez dodania reguł bezpieczeństwa 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ł bezpieczeństwa dane w bazie danych i w zasobniku są lepiej chronione przed niewłaściwym użyciem.
- W terminalu skonfiguruj interfejs CLI do korzystania z utworzonego wcześniej projektu Firebase:
Gdy pojawi się prośba o podanie aliasu, wpiszfirebase use --add
friendlyeats-codelab
. - Aby wdrożyć te reguły zabezpieczeń (a także 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. Sprawdź początkową bazę kodu
W tej sekcji zapoznasz się z kilkoma obszarami początkowej bazy kodu aplikacji, do których dodasz funkcje w tym laboratorium.
Struktura folderów i plików
Poniższa tabela zawiera omówienie 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 narzędziowe, które nie są koniecznie powiązane z Reactem ani Next.js; |
| Kod specyficzny dla Firebase i konfiguracja Firebase |
| statyczne zasoby w aplikacji internetowej, takie jak ikony; |
| Routing za pomocą routera aplikacji Next.js |
| Zależności projektu w npm |
| Konfiguracja specyficzna dla Next.js (działania serwera są włączone) |
| Konfiguracja usługi językowej JavaScript |
Komponenty serwera i klienta
Aplikacja to aplikacja internetowa Next.js, która korzysta z routera aplikacji. Renderowanie po stronie serwera jest używane w całej aplikacji. 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.
Importowanie wyciągów
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. Jest to możliwe dzięki aliasom ścieżek.
Interfejsy API Firebase
Cały kod interfejsu Firebase API jest zawarty w katalogu src/lib/firebase
. Poszczególne komponenty Reacta importują następnie opakowane funkcje z katalogu src/lib/firebase
zamiast importować funkcje Firebase bezpośrednio.
Dane testowe
Przykładowe dane restauracji i opinii znajdują się w pliku src/lib/randomData.js
. Dane z tego pliku są zbierane w kodzie w pliku src/lib/fakeRestaurants.js
.
5. Tworzenie backendu hostingu aplikacji
W tej sekcji skonfigurujesz backend App Hosting, aby obserwować gałąź w repozytorium Git.
Po przeczytaniu tej sekcji będziesz mieć backend App Hosting połączony z repozytorium w GitHubie, który będzie automatycznie ponownie kompilować i wdrażać nową wersję aplikacji za każdym razem, gdy przeniesiesz nowe zatwierdzenie do gałęzi main
.
Utworzenie backendu
- Otwórz stronę hostingu aplikacji w konsoli Firebase:
- Aby rozpocząć proces tworzenia backendu, kliknij „Rozpocznij”. Skonfiguruj backend w ten sposób:
- Wybierz region. W przypadku prawdziwej aplikacji wybierz region najbliżej użytkowników.
- Postępuj zgodnie z instrukcjami w kroku „Importowanie repozytorium GitHub”, aby połączyć utworzone wcześniej repozytorium GitHub.
- Ustawienia wdrażania:
- Pozostaw katalog główny jako
/
- Ustaw gałąź na żywo na
main
- Włącz automatyczne wdrażanie
- Pozostaw katalog główny jako
- Nazwij backend
friendlyeats-codelab
. - W sekcji „Powiąż aplikację internetową Firebase” kliknij „Utwórz nową aplikację internetową Firebase”.
- Kliknij „Zakończ i wdroż”. Po chwili przejdziesz na nową stronę, na której zobaczysz stan nowego backendu hostingu aplikacji.
- Po zakończeniu wdrażania kliknij bezpłatną domenę w sekcji „Domeny”. Zanim zacznie działać, może minąć kilka minut ze względu na propagację DNS.
- Ojej. Po załadowaniu strony 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ę „Dzienniki” zaplecza hostingu aplikacji. Wyświetli się 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
w repozytorium GitHub, w konsoli Firebase zobaczysz nową kompilację i rozpocznie się wdrażanie. Po zakończeniu wdrażania Twoja witryna zostanie automatycznie zaktualizowana.
6. Dodawanie uwierzytelniania do aplikacji internetowej
W tej sekcji dodasz do aplikacji internetowej uwierzytelnianie, aby można było się do niej zalogować.
Dodaj autoryzowaną domenę
Usługa Uwierzytelnianie Firebase będzie akceptować prośby o zalogowanie tylko z dozwolonych domen. Dodamy tu domenę backendu hostingu aplikacji do listy zatwierdzonych domen w Twoim projekcie.
- Skopiuj domenę backendu hostingu aplikacji ze strony „Przegląd” hostingu aplikacji.
- Otwórz kartę Ustawienia uwierzytelniania i wybierz Autoryzowane domeny.
- Kliknij przycisk Dodaj domenę.
- Wpisz domenę backendu hostingu aplikacji.
- Kliknij Dodaj.
Wdrażanie funkcji logowania i wylogowywania
- W pliku
src/lib/firebase/auth.js
zastąp funkcjeonAuthStateChanged
,onIdTokenChanged
,signInWithGoogle
isignOut
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 korzysta z tych interfejsów API Firebase:
Firebase API | Opis |
Dodaje obserwatora zmian stanu logowania użytkownika. | |
Dodaje obserwatora zmian tokena identyfikacyjnego użytkownika. | |
Tworzy instancję dostawcy uwierzytelniania Google. | |
Rozpoczyna proces uwierzytelniania oparty na oknie dialogowym. | |
Wylogowuje użytkownika. |
W pliku src/components/Header.jsx
kod wywołuje już funkcje signInWithGoogle
i signOut
.
Wysyłanie stanu uwierzytelniania na serwer
Aby przekazać stan uwierzytelniania na serwer, użyjemy plików cookie. Gdy stan uwierzytelniania w kliencie ulegnie zmianie, 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 };
}
Weryfikowanie zmian
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) w czasie działania serwera. Jeśli w trakcie cyklu życia strony po jej początkowym wczytaniu nastąpią jakiekolwiek aktualizacje uwierzytelniania, obsłuży je funkcja onAuthStateChanged
.
Teraz nadszedł czas na wdrożenie nowej wersji i sprawdzenie, co zostało utworzone.
- Utwórz zatwierdzenie z komunikatem „Add authentication” (Dodaj uwierzytelnianie) i prześlij je do repozytorium GitHub.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- Sprawdź nowe zachowanie uwierzytelniania:
- Odśwież aplikację internetową w przeglądarce. W nagłówku pojawi się Twoja nazwa wyświetlana.
- Wyloguj się i zaloguj jeszcze raz. Możesz powtórzyć ten krok w przypadku innych użytkowników.
- Opcjonalnie: kliknij prawym przyciskiem myszy aplikację internetową, wybierz Wyświetl źródło strony i wyszukaj wyświetlaną nazwę. Pojawia się w surowym kodzie HTML zwróconym z serwera.
7. Wyświetlanie informacji o restauracji
Aplikacja internetowa zawiera przykładowe dane dotyczące restauracji i opinii.
Dodawanie co najmniej 1 restauracji
Aby wstawić przykładowe dane restauracji do lokalnej bazy danych Cloud Firestore, wykonaj te czynności:
- Zaloguj się w aplikacji internetowej, jeśli jeszcze tego nie zrobiono. Następnie kliknij
> Dodaj przykładowe restauracje.
- W konsoli Firebase na stronie Baza danych Firestore kliknij restaurants. Widzisz dokumenty najwyższego poziomu documents w kolekcji restauracji, z których każdy reprezentuje jedną restaurację.
- Kliknij kilka dokumentów, aby poznać właściwości dokumentu restauracji.
Wyświetlanie listy restauracji
W bazie danych Cloud Firestore znajdują się teraz restauracje, które aplikacja internetowa Next.js może wyświetlać.
Aby zdefiniować kod pobierania danych:
- W pliku
src/app/page.js
znajdź komponent serwera<Home />
i sprawdź wywołanie funkcjigetRestaurants
, która pobiera listę restauracji w czasie działania serwera. FunkcjęgetRestaurants
wdrożysz w tych krokach. - W pliku
src/lib/firebase/firestore.js
zastąp funkcjeapplyQueryFilters
igetRestaurants
tym 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.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- W aplikacji internetowej odśwież stronę. Zdjęcia restauracji pojawiają się na stronie w postaci kafelków.
Sprawdź, czy informacje o restauracjach wczytują się w czasie działania serwera.
W przypadku korzystania z platformy Next.js może nie być oczywiste, kiedy dane są wczytywane w czasie działania serwera lub klienta.
Aby sprawdzić, czy wizytówki restauracji wczytują się 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ą. Listy restauracji nadal się wczytują. Informacje o restauracji są zwracane w odpowiedzi serwera. Gdy JavaScript jest włączony, informacje o restauracji są wypełniane 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 kod pobierania danych Firebase.
Plik src/components/RestaurantListings.jsx
jest komponentem klienta i można go skonfigurować tak, aby uzupełniał znaczniki renderowane na serwerze.
Aby skonfigurować plik src/components/RestaurantListings.jsx
do wypełniania znaczników renderowanych po stronie serwera, wykonaj te czynności:
- W pliku
src/components/RestaurantListings.jsx
zwróć uwagę na ten kod, który jest 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 wprowadzana jest zmiana.
- W pliku
src/lib/firebase/firestore.js
zastą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);
});
}
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” (Nasłuchiwanie aktualizacji restauracji w czasie rzeczywistym) i prześlij je do repozytorium GitHub.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- W aplikacji internetowej kliknij
> Dodaj przykładowe restauracje. Jeśli funkcja migawki jest prawidłowo wdrożona, restauracje będą się pojawiać 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.js
zastą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 średniej obliczonej 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, np. data.get("text")
, aby pobrać wartość tekstową z ładunku przesłanego formularza.
Aby przetworzyć przesłany formularz opinii za pomocą działania serwera Next.js, wykonaj te czynności:
- W pliku
src/components/ReviewDialog.jsx
znajdź atrybutaction
w elemencie<form>
.
<form action={handleReviewFormSubmission}>
Wartość atrybutu action
odnosi się do funkcji, którą zaimplementujesz w następnym kroku.
- W pliku
src/app/actions.js
zastąp funkcjęhandleReviewFormSubmission()
tym kodem:
// 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"),
});
}
Dodawanie opinii o restauracji
Wdrożono obsługę przesyłania opinii, 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” (Zezwól użytkownikom na przesyłanie opinii o restauracjach) i prześlij je do repozytorium GitHub.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- 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 w panelu Dodaj dokument wyszukaj i wybierz dokument restauracji, którą oceniasz.
- W panelu Rozpocznij zbieranie kliknij 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 umożliwi zastąpienie obrazu powiązanego z restauracją po zalogowaniu się. Prześlij obraz do Firebase Storage i zaktualizuj 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.jsx
sprawdź 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ć w tej funkcji żadnych zmian, ale w kolejnych krokach zaimplementujesz działanie funkcji updateRestaurantImage()
.
- W pliku
src/lib/firebase/storage.js
zastą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ż wdrożona. Ta funkcja aktualizuje istniejący dokument restauracji w Cloud Firestore, dodając do niego zaktualizowany adres URL obrazu.
Sprawdź funkcję przesyłania obrazów.
Aby sprawdzić, czy obraz przesyła się zgodnie z oczekiwaniami, wykonaj te czynności:
- Utwórz zatwierdzenie z komunikatem „Allow users to change each restaurants' photo” (Zezwól użytkownikom na zmianę zdjęcia każdej restauracji) i prześlij je do repozytorium GitHub.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- 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.
- Otwórz folder reprezentujący 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 sprawdzić, co myślą o restauracji inni, bez konieczności czytania każdej opinii.
Przechowywanie klucza interfejsu Gemini API w usłudze Cloud Secret Manager
- Aby korzystać z interfejsu Gemini API, musisz mieć klucz interfejsu API. Otwórz Google AI Studio i kliknij „Utwórz klucz interfejsu API”.
- W polu „Wyszukaj projekty Google Cloud” wybierz projekt Firebase. Każdy projekt Firebase jest oparty na projekcie Google Cloud.
- App Hosting jest zintegrowany z Cloud Secret Manager, co umożliwia bezpieczne przechowywanie wartości wrażliwych, 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 tajnej, 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 testów lokalnych, wybierz „Środowisko produkcyjne”.
- Gdy pojawi się pytanie, czy chcesz przyznać dostęp, aby konto usługi backendu mogło uzyskać dostęp do klucza tajnego, wybierz „Tak”.
- Gdy pojawi się pytanie, czy nowy klucz 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.
Wdrażanie komponentu podsumowania opinii
- W pliku
src/components/Reviews/ReviewSummary.jsx
zastąp funkcjęGeminiSummary
tym 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://firebase.google.com/docs/genkit/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.
- Otwórz stronę hostingu aplikacji w konsoli Firebase i poczekaj, aż nowe wdrożenie się zakończy.
- Otwórz stronę restauracji. U góry powinna być widoczna podsumowująca wszystkie opinie na stronie.
- Dodaj nową opinię i odśwież stronę. Powinno pojawić się podsumowanie zmiany.
11. Podsumowanie
Gratulacje! Dowiedzieliśmy się, jak używać Firebase do dodawania funkcji i funkcjonalności do aplikacji Next.js. W szczególności użyliśmy tych usług:
- Firebase App Hosting, aby automatycznie tworzyć i wdrażać kod Next.js za każdym razem, gdy przenosisz go do skonfigurowanej gałęzi.
- Uwierzytelnianie Firebase, aby włączyć funkcje logowania i wylogowywania.
- Cloud Firestore na potrzeby danych restauracji i opinii o restauracjach.
- Cloud Storage dla Firebase na potrzeby zdjęć restauracji.