Informacje o tym ćwiczeniu (w Codelabs)
1. Zanim zaczniesz
Z tego Codelab dowiesz się, jak zintegrować Firebase z aplikacją internetową Next.js o nazwie Friendly Eats, która jest stroną z opiniami o restauracjach.
Ukończona aplikacja internetowa zawiera przydatne funkcje, które pokazują, jak Firebase może Ci pomóc w tworzeniu aplikacji Next.js. Do tych funkcji należą:
- Automatyczne kompilowanie i wdrażanie: ten warsztat z kodowaniem korzysta z Firebase App Hosting, aby automatycznie kompilować i wdrażać kod Next.js za każdym razem, gdy przenosisz go do skonfigurowanej gałęzi.
- Logowanie się i wylogowywanie: w ukończonej aplikacji internetowej możesz się zalogować i wylogować za pomocą Google. Logowaniem i trwałością użytkowników zarządza się wyłącznie za pomocą Uwierzytelniania Firebase.
- Zdjęcia: gotowa aplikacja internetowa umożliwia zalogowanym użytkownikom przesyłanie zdjęć restauracji. Zasoby obrazów są przechowywane w Cloud Storage dla Firebase. Pakiet Firebase JavaScript SDK udostępnia publiczny URL przesłanych obrazów. Ten publiczny adres URL jest następnie przechowywany w dokumentach 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 recenzjach 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ć używaną metodę sortowania. Dane są pobierane z Cloud Firestore, a zapytania do Firestore są stosowane na podstawie użytych filtrów.
Wymagania wstępne
- Konto GitHub
- znajomość Next.js i JavaScriptu;
Czego się nauczysz
- Jak korzystać z Firebase z platformą Next.js App Router i renderowaniem po stronie serwera.
- Jak zapisywać obrazy w Cloud Storage dla Firebase.
- Jak odczytywać i zapisywać dane w bazie danych Cloud Firestore.
- Jak korzystać z funkcji logowania się przez Google w pakiecie SDK Firebase JavaScript.
Czego potrzebujesz
- Git
- najnowsza stabilna wersja Node.js,
- 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
Ten warsztat programistyczny zawiera podstawową bazę kodu aplikacji i korzysta z wiersza poleceń Firebase.
Tworzenie repozytorium GitHub
Źródło kodu ćwiczeń znajdziesz na stronie https://github.com/firebase/friendlyeats-web. Repozytorium zawiera przykładowe projekty na wiele platform. Ten kodlab używa 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 swojego repozytorium:
- Za pomocą terminala utwórz nowy folder na komputerze i przejdź do nowego katalogu:
mkdir codelab-friendlyeats-web
cd codelab-friendlyeats-web - Aby pobrać tylko folder
nextjs-start
, użyj pakietu npm giget:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- Śledź zmiany lokalnie za pomocą git:
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ę.
- Skopiuj nowy adres URL utworzony przez GitHub. Wygląda on 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 miejsce zarezerwowane dla zmiennej
<REPOSITORY_URL>
rzeczywistym adresem URL repozytorium.git remote add origin <REPOSITORY_URL>
git push -u origin main - W repozytorium GitHub powinien teraz być widoczny kod startowy.
Instalowanie lub aktualizowanie 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 niższą wersję lub wiersz poleceń Firebase nie jest zainstalowany, 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 użyj innej opcji instalacji.
Logowanie się 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ła dane. - W przeglądarce wybierz swoje 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
- W konsoli Firebase kliknij Dodaj projekt.
- W polu tekstowym Wpisz nazwę projektu wpisz
FriendlyEats Codelab
(lub wybraną nazwę projektu), a potem kliknij Dalej. - W tym ćwiczeniu nie potrzebujesz Google Analytics, więc wyłącz opcję Włącz Google Analytics w tym projekcie.
- Kliknij Utwórz projekt.
- Poczekaj, aż projekt zostanie przygotowany, a potem kliknij Dalej.
- W projekcie Firebase otwórz Ustawienia projektu. Zapisz identyfikator projektu, bo będzie Ci on potrzebny później. Ten unikalny identyfikator służy do identyfikowania Twojego projektu (np. w wierszu poleceń Firebase).
Przejdź na wyższy abonament Firebase
Aby korzystać z hostingu aplikacji i Cloud Storage for Firebase, projekt Firebase musi być objęty abonamentem płatność według wykorzystania (Blaze), co oznacza, że jest połączony z kontem płatności Google 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 bezpłatnego okresu próbnego na koncie płatności Cloud.
- Jeśli wykonujesz to ćwiczenie w ramach wydarzenia, zapytaj organizatora, czy są dostępne jakieś kredyty Cloud.
Aby przenieść projekt na abonament Blaze:
- W konsoli Firebase wybierz uaktualnienie abonamentu.
- 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 poziom abonamentu musisz utworzyć konto rozliczeniowe Cloud, konieczne może być powrót do procesu przejścia w konsoli Firebase, aby go dokończyć.
Dodawanie aplikacji internetowej do projektu Firebase
- W swoim projekcie Firebase otwórz stronę Omówienie projektu, a potem kliknij
Internet.
Jeśli masz już aplikacje zarejestrowane w projekcie, kliknij Dodaj aplikację, aby wyświetlić ikonę Internetu. - W polu tekstowym Nazwa skrótowa aplikacji wpisz zapadającą w pamięć nazwę skrótową aplikacji, np.
My Next.js app
. - Nie zaznaczaj pola wyboru Skonfiguruj również Hosting Firebase dla tej aplikacji.
- Kliknij Zarejestruj aplikację > Kontynuuj w konsoli.
Konfigurowanie usług Firebase w konsoli Firebase
Konfigurowanie uwierzytelniania
- W konsoli Firebase otwórz sekcję Uwierzytelnianie.
- Kliknij Rozpocznij.
- W kolumnie Dodatkowi dostawcy kliknij Google > Włącz.
- W polu tekstowym Nazwa projektu widoczna publicznie wpisz zapadającą w pamięć nazwę, np.
My Next.js app
. - W menu Adres e-mail pomocy dla projektu wybierz swój adres e-mail.
- Kliknij Zapisz.
Konfigurowanie Cloud Firestore
- W panelu po lewej stronie w konsoli Firebase rozwiń Kompilacja, a potem kliknij Baza danych Firestore.
- Kliknij Utwórz bazę danych.
- Pozostaw wartość
(default)
w polu Identyfikator bazy danych. - Wybierz lokalizację bazy danych, a potem kliknij Dalej.
W przypadku prawdziwej aplikacji wybierz lokalizację blisko użytkowników. - Kliknij Rozpocznij w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł bezpieczeństwa.
W dalszej części tego Codelab dodasz reguły bezpieczeństwa, aby chronić swoje dane. Nie udostępniaj ani nie udostępniaj publicznie aplikacji bez dodania reguł bezpieczeństwa dla bazy danych. - Kliknij Utwórz.
Konfigurowanie Cloud Storage dla Firebase
- W panelu po lewej stronie konsoli Firebase rozwiń Kompilacja, a potem kliknij Storage.
- Kliknij Rozpocznij.
- Wybierz lokalizację domyślnego zasobnika Storage.
Zasobniki w regionachUS-WEST1
,US-CENTRAL1
iUS-EAST1
mogą korzystać z poziomu Always Free w Google Cloud Storage. Zasobniki w innych lokalizacjach podlegają cennikom i zasadom korzystania z Google Cloud Storage. - Kliknij Rozpocznij w trybie testowym. Przeczytaj wyłączenie odpowiedzialności dotyczące reguł bezpieczeństwa.
W dalszej części tego Codelab dodasz reguły bezpieczeństwa, które ochronią Twoje dane. Nie udostępniaj ani nie udostępniaj publicznie aplikacji bez dodania reguł bezpieczeństwa dla 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 pojemniku są lepiej chronione przed niewłaściwym użyciem.
- W terminalu skonfiguruj 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órych będziesz potrzebować 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. Sprawdzanie kodu źródłowego bazy danych
W tej sekcji przyjrzysz się kilku obszarom podstawowego kodu źródłowego aplikacji, do których w ramach tego Codelab dodasz funkcje.
Struktura folderów i plików
W tabeli poniżej znajdziesz 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 pomocnicze, które nie są koniecznie powiązane z React lub Next.js; |
| Kod i konfiguracja Firebase |
| komponenty statyczne w aplikacji internetowej, np. ikony; |
| Routing za pomocą routera aplikacji Next.js |
| Zależności projektu w npm |
| Konfiguracja specyficzna dla Next.js (czynności serwera są włączone) |
| Konfiguracja usługi językowej JavaScript |
Komponenty serwera i klienta
Aplikacja jest aplikacją internetową Next.js, która korzysta z App Router. Renderowanie po stronie serwera jest używane w całej aplikacji. Przykładowo plik src/app/page.js
to element 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 tej:
import RatingPicker from "@/src/components/RatingPicker.jsx";
Aplikacja używa symbolu @
, aby uniknąć nieczytelnych ścieżek importu względnych. Jest to możliwe dzięki aliasom ścieżek.
Interfejsy API specyficzne dla Firebase
Cały kod interfejsu API Firebase jest zapakowany w katalogu src/lib/firebase
. Poszczególne komponenty Reacta importują następnie owinięte funkcje z katalogu src/lib/firebase
, a nie bezpośrednio z Firebase.
Dane testowe
Plik src/lib/randomData.js
zawiera dane o fikcyjnej restauracji i recenzjach. Dane z tego pliku są łączone w kodzie w pliku src/lib/fakeRestaurants.js
.
5. Tworzenie backendu hostingu aplikacji
W tej sekcji skonfigurujesz backend Hostowanie aplikacji, aby obserwować gałąź w repozytorium Git.
Po zakończeniu tej sekcji będziesz mieć backend usługi tworzenia aplikacji połączony z repozytorium w GitHub, który automatycznie ponownie skompiluje i wdroży nową wersję aplikacji za każdym razem, gdy prześlesz nowe zatwierdzenie do gałęzi main
.
Utworzenie backendu
- Otwórz w konsoli Firebase stronę Hosting aplikacji:
- Aby rozpocząć proces tworzenia backendu, kliknij „Rozpocznij”. Skonfiguruj backend w ten sposób:
- Wybierz region. W przypadku prawdziwej aplikacji należy wybrać region najbliży użytkownikom.
- Postępuj zgodnie z instrukcjami wyświetlanymi w kroku „Importowanie repozytorium GitHub”, aby połączyć wcześniej utworzone repozytorium GitHub.
- Ustaw ustawienia wdrażania:
- Zachowaj katalog główny jako
/
- Ustaw aktywną gałąź na
main
- Włączanie automatycznego wdrażania
- Zachowaj katalog główny jako
- Nazwij backend
friendlyeats-codelab
. - W sekcji „Połącz aplikację internetową Firebase” kliknij „Utwórz nową aplikację internetową Firebase”.
- Kliknij „Zakończ i wdróż”. Po chwili przeniesiesz się na nową stronę, na której możesz sprawdzić stan nowego backendu usługi Hostowanie aplikacji.
- Po zakończeniu wdrażania kliknij swoją bezpłatną domenę w sekcji „Domeny”. Z powodu propagacji DNS może minąć kilka minut, zanim zmiany zaczną działać.
- 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ę „Logi” w backendzie usługi Hostingu aplikacji. Zobaczysz komunikat o błędzie „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 wypychasz nowe zatwierdzenie do gałęzi main
w repozytorium GitHub, w konsoli Firebase rozpoczyna się nowe kompilowanie i wdrażanie. Po zakończeniu wdrażania Twoja witryna zostanie automatycznie zaktualizowana.
6. Dodawanie uwierzytelniania do aplikacji internetowej
W tej sekcji dodasz uwierzytelnianie do aplikacji internetowej, aby móc się w niej zalogować.
Dodaj autoryzowaną domenę
Usługa Uwierzytelnianie Firebase będzie akceptować tylko żądania logowania z domen, które zezwolisz. Dodamy domenę backendu usługi hostingu aplikacji do listy zatwierdzonych domen w Twoim projekcie.
- Skopiuj domenę backendu hostingu aplikacji ze strony „Przegląd” hostingu aplikacji.
- Otwórz kartę Auth Settings (Uwierzytelnianie – ustawienia) i wybierz Authorized Domains (Autoryzowane domeny).
- Kliknij przycisk Dodaj domenę.
- Wpisz domenę backendu hostingu aplikacji.
- Kliknij Dodaj.
Implementowanie 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 w tokenie identyfikacyjnym użytkownika. | |
Tworzy instancję dostawcy uwierzytelniania Google. | |
Rozpoczyna proces uwierzytelniania za pomocą dialogu. | |
Wyloguj użytkownika. |
W pliku src/components/Header.jsx
kod już wywołuje 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;
}
Odczyt stanu uwierzytelniania na serwerze
Użyjemy aplikacji FirebaseServerApp, aby odzwierciedlić stan uwierzytelniania klienta na serwerze.
Otwórz funkcję src/lib/firebase/serverApp.js
i zastąp ją 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 jako argument (jeśli jest dostępny).
<Header initialUser={currentUser?.toJSON()} />
Oznacza to, że komponent <Header>
renderuje dane użytkownika (jeśli są dostępne) w czasie wykonywania na serwerze. Jeśli w trakcie cyklu życia strony po jej początkowym załadowaniu nastąpią jakieś zmiany uwierzytelniania, obsłuży je element onAuthStateChanged
.
Teraz nadszedł czas na wdrożenie nowej wersji i sprawdzenie jej.
- Utwórz zatwierdzanie z komunikatem „Dodaj uwierzytelnianie” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj na zakończenie nowego wdrożenia.
- Sprawdź nowe zachowanie uwierzytelniania:
- W przeglądarce odśwież aplikację internetową. W nagłówku pojawi się Twoja nazwa wyświetlana.
- Wyloguj się i zaloguj ponownie. 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 znajdź wyświetlaną nazwę. Występuje w surowym kodzie HTML zwróconym z serwera.
7. Wyświetlanie informacji o restauracji
Aplikacja internetowa zawiera przykładowe dane o restauracjach i recenzjach.
Dodawanie co najmniej 1 restauracji
Aby wstawić do lokalnej bazy danych Cloud Firestore dane testowej restauracji:
- Zaloguj się w aplikacji internetowej, jeśli nie masz jeszcze konta. Następnie kliknij
> Dodaj przykładowe restauracje.
- W konsoli Firebase na stronie Baza danych Firestore kliknij restaurants. W kolekcji restauracji zobaczysz najwyższego poziomu dokumenty, z których każdy reprezentuje restaurację.
- Kliknij kilka dokumentów, aby poznać właściwości dokumentu restauracji.
Wyświetlanie listy restauracji
Twoja baza danych Cloud Firestore zawiera teraz restauracje, które aplikacja internetowa Next.js może wyświetlać.
Aby zdefiniować kod pobierania danych:
- W pliku
src/app/page.js
odszukaj komponent serwera<Home />
i sprawdź wywołanie funkcjigetRestaurants
, która pobiera listę restauracji w czasie wykonywania na serwerze. FunkcjęgetRestaurants
wdrażasz w podanych niżej 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 zatwierdzanie z komunikatem „Czytaj listę restauracji z Firestore” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj na zakończenie nowego wdrożenia.
- W aplikacji internetowej odśwież stronę. Zdjęcia restauracji są wyświetlane na stronie w postaci kafelków.
Sprawdź, czy informacje o restauracji wczytują się w czasie działania serwera.
W ramach frameworku Next.js trudno określić, czy dane są wczytywane po stronie serwera czy po stronie klienta.
Aby sprawdzić, czy wizytówki restauracji wczytują się w czasie działania serwera:
- W aplikacji internetowej otwórz Narzędzia deweloperskie i wyłącz JavaScript.
- Odśwież aplikację internetową. Informacje o restauracjach nadal się wczytują. Informacje o restauracji są zwracane w odpowiedzi serwera. Gdy JavaScript jest włączony, informacje o restauracji są hydratyzowane za pomocą kodu JavaScript po stronie klienta.
- W Narzędziach deweloperskich ponownie włącz JavaScript.
Nasłuchiwanie aktualizacji restauracji za pomocą odbiorników zrzutów Cloud Firestore
W poprzedniej sekcji pokazaliśmy, jak wczytać początkowy zestaw restauracji z pliku src/app/page.js
. Plik src/app/page.js
to komponent serwera, który jest renderowany na serwerze, w tym kod pobierania danych Firebase.
Plik src/components/RestaurantListings.jsx
to komponent klienta, który można skonfigurować w celu nasycania znaczników renderowanych na serwerze.
Aby skonfigurować plik src/components/RestaurantListings.jsx
do nasycania znaczników renderowanych na serwerze, wykonaj te czynności:
- W pliku
src/components/RestaurantListings.jsx
zwróć uwagę na ten kod, który jest już w nim zapisany:
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. Funkcja zrzutu zawiera jednak mechanizm wywołania zwrotnego, który jest wywoływany za każdym razem, gdy w zbiorze restauracji zostanie wprowadzona 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 wprowadzane na stronie Baza danych Firestore są teraz odzwierciedlane w aplikacji internetowej w czasie rzeczywistym.
- Utwórz zatwierdzenie z wiadomością „słuchaj aktualizacji restauracji w czasie rzeczywistym” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj na zakończenie nowego wdrożenia.
- W aplikacji internetowej kliknij
> Dodaj przykładowe restauracje. Jeśli funkcja migawki jest prawidłowo zaimplementowana, restauracje będą się wyświetlać 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 aktualne dane o liczbie ocen i średniej obliczonej ocenie.
- 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
Akcją serwera Next.js jest wygodny interfejs API umożliwiający dostęp do danych formularza, np. data.get("text")
, aby uzyskać wartość tekstową z ładunku przesłania formularza.
Aby przetworzyć przesłany formularz opinii, użyj akcji serwera Next.js:
- 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żyłeś obsługę przesyłania opinii, więc możesz teraz sprawdzić, czy opinie są prawidłowo wstawiane do Cloud Firestore.
Aby dodać opinię i sprawdzić, czy została ona dodana do Cloud Firestore, wykonaj te czynności:
- Utwórz zatwierdzanie z komunikatem „Zezwalaj użytkownikom na przesyłanie opinii o restauracjach” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj na zakończenie nowego wdrożenia.
- Odśwież aplikację internetową i na stronie głównej wybierz restaurację.
- Na stronie restauracji kliknij
.
- Wybierz liczbę gwiazdek.
- Napisz opinię.
- Kliknij Prześlij. Opinia pojawi się u góry listy opinii.
- W Cloud Firestore wyszukaj w panelu Dodaj dokument dokument z restauracją, który chcesz ocenić, i go wybierz.
- W panelu Rozpocznij zbieranie wybierz oceny.
- W panelu Dodaj dokument odszukaj dokument, który chcesz sprawdzić, 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 Ci zastąpienie obrazu powiązanego z restauracją po zalogowaniu się. Przesyłasz obraz do Firebase Storage i aktualizujesz adres URL obrazu w dokumencie Cloud Firestore, który reprezentuje restaurację.
Aby zapisać pliki przesłane przez użytkowników z aplikacji internetowej:
- W pliku
src/components/Restaurant.jsx
sprawdź kod, który jest wykonywany, gdy użytkownik prześle 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 następnych krokach musisz zaimplementować 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()
została już wdrożona. Ta funkcja aktualizuje istniejący dokument restauracji w Cloud Firestore, dodając do niego zaktualizowany adres URL obrazu.
Sprawdzanie funkcji przesyłania obrazów
Aby sprawdzić, czy obrazy są przesyłane zgodnie z oczekiwaniami:
- Utwórz zatwierdzenie z wiadomością „Zezwalaj użytkownikom na zmianę zdjęć restauracji” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj 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.
- Otwórz folder reprezentujący restaurację. Przesłany obraz znajduje się w folderze.
10. Streszczanie opinii o restauracji za pomocą generatywnej AI
W tej sekcji dodasz funkcję podsumowania opinii, aby użytkownik 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, musisz mieć klucz interfejsu API. Otwórz Google AI Studio i kliknij „Utwórz klucz API”.
- W polu „Szukaj projekty Google Cloud” wybierz projekt Firebase. Każdy projekt Firebase jest oparty na projekcie Google Cloud.
- Hosting aplikacji integruje się z Cloud Secret Manager, aby umożliwić bezpieczne przechowywanie wartości wrażliwych, takich jak klucze interfejsu API:
- Aby utworzyć nowy obiekt tajny, uruchom w terminalu to polecenie:
firebase apphosting:secrets:set GEMINI_API_KEY
- Gdy pojawi się prośba o wartość tajną, skopiuj i wklej klucz interfejsu Gemini API z Google AI Studio.
- Gdy pojawi się pytanie, czy nowy sekret jest przeznaczony do użytku w wersji produkcyjnej czy do testów lokalnych, wybierz „Wersja produkcyjna”.
- Gdy pojawi się pytanie, czy chcesz przyznać dostęp do sekretu Twojemu koncie usługi w systemie backendowym, wybierz „Tak”.
- Gdy pojawi się pytanie, czy nowy klucz powinien 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 usługi hostowania aplikacji.
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 zatwierdzanie z komunikatem „Użyj AI do podsumowywania opinii” i prześlij je do repozytorium GitHub.
- W konsoli Firebase otwórz stronę Hosting aplikacji i zaczekaj na zakończenie nowego wdrożenia.
- Otwórz stronę restauracji. U góry strony powinno się wyświetlać podsumowanie wszystkich opinii na stronie w jednym zdaniu.
- Dodaj nową opinię i odśwież stronę. Powinna się zmienić treść podsumowania.
11. Podsumowanie
Gratulacje! Dowiedz się, jak za pomocą Firebase dodać funkcje do aplikacji Next.js. W szczególności wykorzystano te elementy:
- Firebase App Hosting do automatycznego kompilowania i wdrażania kodu Next.js za każdym razem, gdy przenosisz go do skonfigurowanej gałęzi.
- Uwierzytelnianie Firebase, aby włączyć funkcje logowania i wylogowywania.
- Cloud Firestore do przechowywania danych o restauracji i opinii o niej.
- Cloud Storage dla Firebase na potrzeby zdjęć restauracji.