1. Prima di iniziare
In questo codelab imparerai a integrare Firebase con un'app web Next.js chiamata Friendly Eats, un sito web per le recensioni di ristoranti.

L'app web completata offre funzionalità utili che mostrano come Firebase può aiutarti a creare app Next.js. Queste funzionalità includono:
- Creazione ed esecuzione del deployment automatiche: questo codelab utilizza Firebase App Hosting per creare ed eseguire automaticamente il deployment del codice Next.js ogni volta che esegui il push a un branch configurato.
- Accesso e uscita: l'app web completata ti consente di accedere con Google e di uscire. L'accesso e la persistenza degli utenti sono gestiti interamente tramite Firebase Authentication.
- Immagini: l'app web completata consente agli utenti che hanno eseguito l'accesso di caricare immagini dei ristoranti. Gli asset immagine vengono archiviati in Cloud Storage for Firebase. L'SDK Firebase JavaScript fornisce un URL pubblico per le immagini caricate. Questo URL pubblico viene quindi archiviato nel documento del ristorante pertinente in Cloud Firestore.
- Recensioni: l'app web completata consente agli utenti che hanno eseguito l'accesso di pubblicare recensioni dei ristoranti, composte da una valutazione a stelle e un messaggio di testo. Le informazioni sulle recensioni vengono archiviate in Cloud Firestore.
- Filtri: l'app web completata consente agli utenti che hanno eseguito l'accesso di filtrare l'elenco dei ristoranti in base a categoria, località e prezzo. Puoi anche personalizzare il metodo di ordinamento utilizzato. L'accesso ai dati avviene da Cloud Firestore e le query di Firestore vengono applicate in base ai filtri utilizzati.
Prerequisiti
- Un account GitHub
- Conoscenza di Next.js e JavaScript
Obiettivi didattici
- Come utilizzare Firebase con il router di app Next.js e il rendering lato server.
- Come rendere persistenti le immagini in Cloud Storage for Firebase.
- Come leggere e scrivere dati in un database Cloud Firestore.
- Come utilizzare Accedi con Google con l'SDK Firebase JavaScript.
Che cosa ti serve
- Git
- Una versione stabile recente di Node.js
- Un browser a tua scelta, ad esempio Google Chrome
- Un ambiente di sviluppo con un editor di codice e un terminale
- Un Account Google per la creazione e la gestione del progetto Firebase
- La possibilità di eseguire l'upgrade del progetto Firebase al piano tariffario Blaze
2. Configura l'ambiente di sviluppo e il repository GitHub
Questo codelab fornisce il codebase iniziale dell'app e si basa sull'interfaccia a riga di comando di Firebase.
Crea un repository GitHub
Il codice sorgente del codelab è disponibile all'indirizzo https://github.com/firebase/friendlyeats-web. Il repository contiene progetti di esempio per più piattaforme. Tuttavia, questo codelab utilizza solo la directory nextjs-start. Prendi nota delle seguenti directory:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Copia la cartella nextjs-start nel tuo repository:
- Utilizzando un terminale, crea una nuova cartella sul computer e passa alla nuova directory:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web - Utilizza il pacchetto npm giget per recuperare solo la cartella
nextjs-start:npx giget@latest "gh:firebase/friendlyeats-web/nextjs-start#master" . --install - Monitora le modifiche localmente con Git:
git init git add . git commit -m "Codelab starting point" git branch -M main - Crea un nuovo repository GitHub: https://github.com/new. Assegnale il nome che preferisci.
- A seconda di come esegui l'autenticazione su GitHub (HTTPS o SSH), copia il nuovo URL creato da GitHub:
https://github.com/<USER_NAME>/<REPOSITORY_NAME>.gitogit@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
- Esegui il push delle modifiche locali nel nuovo repository GitHub utilizzando il comando seguente. Sostituisci il segnaposto
<REPOSITORY_URL>con l'URL del tuo repository effettivo.git remote add origin <REPOSITORY_URL> git push -u origin main - Ora dovresti vedere il codice di avvio nel tuo repository GitHub.
Installa o aggiorna l'interfaccia a riga di comando di Firebase
Esegui questo comando per verificare di aver installato l'interfaccia a riga di comando di Firebase e che sia la versione 14.1.0 o successiva:
firebase --version
Se vedi una versione precedente o se l'interfaccia a riga di comando di Firebase non è installata, esegui il comando di installazione:
npm install -g firebase-tools@latest
Se non riesci a installare l'interfaccia a riga di comando di Firebase a causa di errori di autorizzazione, consulta la documentazione di npm o utilizza un'altra opzione di installazione.
Accedi a Firebase
- Esegui questo comando per accedere all'interfaccia a riga di comando di Firebase:
firebase login
- A seconda che tu voglia o meno che Firebase raccolga i dati, inserisci
YoN. - Nel browser, seleziona il tuo Account Google e fai clic su Consenti.
3. Configura il progetto Firebase
In questa sezione configurerai un progetto Firebase e vi assocerai un'app web Firebase. Inoltre, configurerai i servizi Firebase utilizzati dall'app web di esempio.
Crea un progetto Firebase
- Accedi alla console Firebase utilizzando lo stesso Account Google utilizzato nel passaggio precedente.
- Fai clic sul pulsante per creare un nuovo progetto, quindi inserisci un nome per il progetto (ad esempio
FriendlyEats Codelab).
- Fai clic su Continua.
- Se richiesto, leggi e accetta i Termini di Firebase, quindi fai clic su Continua.
- (Facoltativo) Attiva l'assistenza AI nella console Firebase (chiamata "Gemini in Firebase").
- Per questo codelab, non hai bisogno di Google Analytics, quindi disattiva l'opzione Google Analytics.
- Fai clic su Crea progetto, attendi il provisioning del progetto, quindi fai clic su Continua.
Esegui l'upgrade del piano tariffario Firebase
Per utilizzare Firebase App Hosting e Cloud Storage for Firebase, il tuo progetto Firebase deve essere incluso nel piano tariffario Blaze con pagamento a consumo, il che significa che è collegato a un account di fatturazione Cloud.
- Un account di fatturazione Cloud richiede un metodo di pagamento, ad esempio una carta di credito.
- Se non hai mai utilizzato Firebase e Google Cloud, verifica se hai diritto a un credito di 300 $ e a un account di fatturazione Cloud per la prova senza costi.
- Se stai svolgendo questo codelab nell'ambito di un evento, chiedi all'organizzatore se sono disponibili crediti Cloud.
Per eseguire l'upgrade del progetto al piano Blaze, segui questi passaggi:
- Nella console Firebase, seleziona l'opzione per eseguire l'upgrade del piano.
- Seleziona il piano Blaze. Segui le istruzioni sullo schermo per collegare un account di fatturazione Cloud al tuo progetto.
Se hai dovuto creare un account di fatturazione Cloud nell'ambito di questo upgrade, potresti dover tornare al flusso di upgrade nella console Firebase per completare l'upgrade.
Aggiungi un'app web al tuo progetto Firebase
- Vai alla Panoramica del progetto nel tuo progetto Firebase, fai clic su Aggiungi app e poi su Web.
- Nella casella di testo Nickname app, inserisci un nickname facile da ricordare, ad esempio
My Next.js app. - Lascia deselezionata la casella di controllo Inoltre, configura Firebase Hosting per questa app.
- Fai clic su Registra app > Vai alla console.
Configura i servizi Firebase nella console Firebase
Configura l'autenticazione
- Nel riquadro a sinistra della console Firebase, espandi Build e poi seleziona Authentication.
- Fai clic su Inizia.
- Nella colonna Provider di accesso, fai clic su Google > Attiva.
- Nella casella di testo Nome visibile al pubblico del progetto, inserisci un nome facile da ricordare, ad esempio
My Next.js app. - Dal menu a discesa Email di assistenza per il progetto, seleziona il tuo indirizzo email.
- Fai clic su Salva.
Configura Cloud Firestore
- Nel riquadro a sinistra della console Firebase, espandi Build e seleziona Database Firestore.
- Fai clic su Crea database.
- Scegli Standard Edition e fai clic su Avanti.
- Non modificare l'ID database, lascialo impostato su
(default). - Seleziona una località per il database, quindi fai clic su Avanti.
Per un'app reale, devi scegliere una località vicina ai tuoi utenti. - Fai clic su Avvia in modalità di test. Leggi il disclaimer sulle regole di sicurezza.
Più avanti in questo codelab, aggiungerai regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il tuo database. - Fai clic su Crea.
Configura Cloud Storage for Firebase
- Nel riquadro a sinistra della console Firebase, espandi Build e seleziona Storage.
- Fai clic su Inizia.
- Seleziona una località per il bucket di archiviazione predefinito.
I bucket inUS-WEST1,US-CENTRAL1eUS-EAST1possono usufruire del livello "Always Free" per Google Cloud Storage. I bucket in tutte le altre località seguono i prezzi e l'utilizzo di Google Cloud Storage. - Fai clic su Avvia in modalità di test. Leggi il disclaimer sulle regole di sicurezza.
Più avanti in questo codelab, aggiungerai regole di sicurezza per proteggere i tuoi dati. Non distribuire o esporre pubblicamente un'app senza aggiungere regole di sicurezza per il bucket di Storage. - Fai clic su Crea.
Esegui il deployment delle regole di sicurezza
Il codice contiene già insiemi di regole di sicurezza per Firestore e per Cloud Storage for Firebase. Dopo aver eseguito il deployment delle regole di sicurezza, i dati nel database e nel bucket sono protetti meglio da un uso improprio.
- Nel terminale, configura l'interfaccia a riga di comando in modo da utilizzare il progetto Firebase creato in precedenza:
Quando viene richiesto un alias, inseriscifirebase use --add
friendlyeats-codelab. - Per eseguire il deployment di queste regole di sicurezza (nonché degli indici che saranno necessari in un secondo momento), esegui questo comando nel terminale:
firebase deploy --only firestore,storage
- Se ti viene chiesto:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?", premiEnterper selezionare Sì.
4. Esamina il codebase iniziale
In questa sezione esaminerai alcune aree del codebase iniziale dell'app a cui aggiungerai funzionalità in questo codelab.
Struttura di cartelle e file
La tabella seguente contiene una panoramica della struttura di cartelle e file dell'app:
Cartelle e file | Descrizione |
| Componenti React per filtri, intestazioni, dettagli dei ristoranti e recensioni |
| Funzioni di utilità che non sono necessariamente associate a React o Next.js |
| Codice specifico di Firebase e configurazione di Firebase |
| Asset statici nell'app web, come le icone |
| Routing con il router di app Next.js |
| Dipendenze del progetto con npm |
| Configurazione specifica di Next.js (le azioni del server sono abilitate) |
| Configurazione del servizio di linguaggio JavaScript |
Componenti server e client
L'app è un'app web Next.js che utilizza il router dell'app. Il rendering lato server viene utilizzato in tutta l'app. Ad esempio, il file src/app/page.js è un componente lato server responsabile della pagina principale. Il file src/components/RestaurantListings.jsx è un componente client indicato dall'istruzione "use client" all'inizio del file.
Istruzioni di importazione
Potresti notare istruzioni di importazione come le seguenti:
import RatingPicker from "@/src/components/RatingPicker.jsx";
L'app utilizza il simbolo @ per evitare percorsi di importazione relativi complessi, il che è reso possibile dagli alias dei percorsi.
API specifiche di Firebase
Tutto il codice dell'API Firebase è inserito nella directory src/lib/firebase. I singoli componenti React importano quindi le funzioni con wrapper dalla directory src/lib/firebase, anziché importare direttamente le funzioni Firebase.
Dati fittizi
I dati fittizi relativi a ristoranti e recensioni sono contenuti nel file src/lib/randomData.js. I dati di questo file vengono assemblati nel codice del file src/lib/fakeRestaurants.js.
5. Crea un backend App Hosting
In questa sezione configurerai un backend App Hosting per monitorare un branch nel tuo repository Git.
Al termine di questa sezione, avrai un backend App Hosting connesso al tuo repository in GitHub che eseguirà automaticamente la nuova build e il deployment di una nuova versione della tua app ogni volta che esegui il push di un nuovo commit nel tuo branch main.
Crea un backend
- Vai alla pagina App Hosting nella console Firebase.
- Fai clic su Inizia per avviare il flusso di creazione del backend.
- Scegli un'area geografica. Per un'app reale, devi scegliere la regione più vicina ai tuoi utenti.
- Segui i prompt nel passaggio Importa un repository GitHub per configurare l'autenticazione GitHub.
- In Repository, seleziona Concedi l'accesso a un nuovo repository in GitHub e segui i prompt per abilitare l'accesso al repository GitHub che hai creato in precedenza.
- Fai clic su Aggiorna elenco per aggiornare l'elenco, poi seleziona il repository e fai clic su Avanti.
- Configura le impostazioni di deployment:
- Imposta il branch attivo su
main. - Mantieni la directory root come
/. - Abilita le implementazioni automatiche.
- Imposta il branch attivo su
- Assegna un nome al backend
friendlyeats-codelabe fai clic su Avanti. - In Associa un'app web Firebase, scegli Seleziona un'app web Firebase esistente e seleziona l'app che hai aggiunto dall'elenco.
- Fai clic su Termina ed esegui il deployment. Verrà visualizzata una nuova pagina in cui puoi vedere lo stato del tuo nuovo backend App Hosting.
- Fai clic su Visualizza per visualizzare ulteriori informazioni sul deployment di App Hosting, tra cui lo stato dell'implementazione, i log e i dettagli di utilizzo.
- Al termine dell'implementazione, fai clic per aprire l'URL del sito in Domini. L'attivazione potrebbe richiedere alcuni minuti a causa della propagazione del DNS.
- Oh oh. Quando carichi la pagina, vedrai un messaggio di errore che dice "Errore dell'applicazione: si è verificata un'eccezione lato server (per ulteriori informazioni, consulta i log del server)".
- Nella console Firebase, controlla la scheda Log del backend di App Hosting. Verrà visualizzato un log "Error: not implemented". Risolveremo questo problema nel passaggio successivo, quando aggiungeremo l'autenticazione.
Hai eseguito il deployment dell'app web iniziale. Ogni volta che esegui il push di un nuovo commit nel ramo main del tuo repository GitHub, vedrai l'inizio di una nuova build e di un nuovo lancio nella console Firebase e il tuo sito verrà aggiornato automaticamente al termine del lancio.
6. Aggiungi l'autenticazione all'app web
In questa sezione aggiungerai l'autenticazione all'app web in modo da poter accedere.
Aggiungi un dominio autorizzato
Firebase Authentication accetterà le richieste di accesso solo dai domini che consenti. Qui aggiungeremo il dominio del backend di App Hosting all'elenco dei domini approvati nel tuo progetto.
- Apri la pagina App Hosting e fai clic su Visualizza sotto il sito di cui hai eseguito il deployment per accedere alla pagina Panoramica. Copia il nome di dominio del backend App Hosting.
- Vai alla scheda Impostazioni di autenticazione e scegli il progetto a cui vuoi aggiungere un dominio autorizzato. Quindi, individua la sezione Domini autorizzati e fai clic su di essa.
- Fai clic sul pulsante Aggiungi dominio.
- Inserisci il dominio del backend App Hosting.
- Fai clic su Aggiungi.
Implementa le funzioni di accesso e uscita
Nel file src/lib/firebase/auth.js, sostituisci le funzioni onAuthStateChanged, onIdTokenChanged, signInWithGoogle e signOut con il seguente codice:
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);
}
}
Questo codice utilizza le seguenti API Firebase:
API Firebase | Descrizione |
Aggiunge un osservatore per le modifiche allo stato di accesso dell'utente. | |
Aggiunge un osservatore per le modifiche al token ID dell'utente. | |
Crea un'istanza del provider di autenticazione Google. | |
Avvia un flusso di autenticazione basato su finestra di dialogo. | |
Disconnette l'utente. |
Nel file src/components/Header.jsx, il codice richiama già le funzioni signInWithGoogle e signOut.
Invia lo stato di autenticazione al server
Per passare lo stato di autenticazione al server, utilizzeremo i cookie. Ogni volta che lo stato di autenticazione cambia nel client, aggiorneremo il cookie __session.
In src/components/Header.jsx, sostituisci la funzione useUserSession con il seguente codice:
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;
}
Leggi lo stato di autenticazione sul server
Utilizzeremo FirebaseServerApp per eseguire il mirroring dello stato di autenticazione del client sul server.
Apri src/lib/firebase/serverApp.js e sostituisci la funzione 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 };
}
Verificare le modifiche
Il layout principale nel file src/app/layout.js esegue il rendering dell'intestazione e passa l'utente, se disponibile, come proprietà.
<Header initialUser={currentUser?.toJSON()} />
Ciò significa che il componente <Header> esegue il rendering dei dati utente, se disponibili, durante il runtime del server. Se si verificano aggiornamenti dell'autenticazione durante il ciclo di vita della pagina dopo il caricamento iniziale, il gestore onAuthStateChanged li gestisce.
Ora è il momento di implementare una nuova build e verificare ciò che hai creato.
- Crea un commit con il messaggio "Add authentication" ed eseguine il push nel tuo repository GitHub.
git add . git commit -m "Add authentication" git push - Apri la pagina App Hosting e, al termine del nuovo lancio, fai clic sull'URL del sito per aprirlo.
- Autenticazione di test:
- Accedi con il tuo Account Google e verifica che il tuo nome visualizzato venga mostrato nell'intestazione dopo l'accesso.
- Esci e accedi nuovamente. Puoi ripetere questo passaggio con utenti diversi.
- (Facoltativo) Fai clic con il tasto destro del mouse sull'app web, seleziona Visualizza sorgente pagina e cerca il nome visualizzato. Viene visualizzato nell'origine HTML non elaborata restituita dal server.
7. Visualizza le informazioni sul ristorante
L'app web include dati fittizi per ristoranti e recensioni.
Aggiungi uno o più ristoranti
Per inserire dati fittizi sui ristoranti nel tuo database Cloud Firestore locale, segui questi passaggi:
- Se non l'hai ancora fatto, accedi all'app web. Poi, seleziona
> Aggiungi ristoranti di esempio. Tieni presente che non vediamo alcun ristorante nell'app web Friendly Eats perché non abbiamo ancora configurato il codice di recupero dei dati. Risolveremo questo problema nel passaggio successivo. - Nella console Firebase, nella pagina Database Firestore, seleziona restaurants. Vedi i documenti di primo livello nella raccolta dei ristoranti, ognuno dei quali rappresenta un ristorante.
- Fai clic su alcuni documenti per esplorare le proprietà di un documento di un ristorante.
Visualizza l'elenco dei ristoranti
Il tuo database Cloud Firestore ora contiene i ristoranti che l'app web Next.js può visualizzare.
Per definire il codice di recupero dei dati, segui questi passaggi:
- Nel file
src/app/page.js, individua il componente server<Home />ed esamina la chiamata alla funzionegetRestaurants, che recupera un elenco di ristoranti in fase di esecuzione del server. Implementerai la funzionegetRestaurantsnei passaggi seguenti. - Nel file
src/lib/firebase/firestore.js, sostituisci le funzioniapplyQueryFiltersegetRestaurantscon il seguente codice:
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(),
};
});
}
- Crea un commit con il messaggio "Read the list of restaurants from Firestore" e invialo al tuo repository GitHub.
git add . git commit -m "Read the list of restaurants from Firestore" git push - Apri la pagina App Hosting nella console Firebase e attendi il completamento del nuovo lancio.
- Nell'app web, aggiorna la pagina. Le immagini del ristorante vengono visualizzate come riquadri nella pagina.
Verifica che le schede dei ristoranti vengano caricate in fase di esecuzione del server
Quando utilizzi il framework Next.js, potrebbe non essere ovvio quando i dati vengono caricati in fase di esecuzione lato server o lato client.
Per verificare che le schede dei ristoranti vengano caricate in fase di esecuzione del server, segui questi passaggi:
- Nell'app web, apri DevTools e disattiva JavaScript.

- Aggiorna l'app web. Le schede dei ristoranti vengono comunque caricate. Le informazioni sul ristorante vengono restituite nella risposta del server. Quando JavaScript è abilitato, le informazioni sul ristorante vengono integrate tramite il codice JavaScript lato client.
- In DevTools, riattiva JavaScript.
Ascolta gli aggiornamenti dei ristoranti con i listener di snapshot di Cloud Firestore
Nella sezione precedente, hai visto come è stato caricato l'insieme iniziale di ristoranti dal file src/app/page.js. Il file src/app/page.js è un componente server e viene visualizzato sul server, incluso il codice di recupero dei dati di Firebase.
Il file src/components/RestaurantListings.jsx è un componente client e può essere configurato per l'idratazione del markup sottoposto a rendering lato server.
Per configurare il file src/components/RestaurantListings.jsx in modo da idratare il markup sottoposto a rendering lato server, segui questi passaggi:
- Nel file
src/components/RestaurantListings.jsx, osserva il seguente codice, che è già stato scritto per te:
useEffect(() => {
return getRestaurantsSnapshot((data) => {
setRestaurants(data);
}, filters);
}, [filters]);
Questo codice richiama la funzione getRestaurantsSnapshot(), che è simile alla funzione getRestaurants() che hai implementato in un passaggio precedente. Tuttavia, questa funzione snapshot fornisce un meccanismo di callback in modo che il callback venga richiamato ogni volta che viene apportata una modifica alla raccolta del ristorante.
- Nel file
src/lib/firebase/firestore.js, sostituisci la funzionegetRestaurantsSnapshot()con il seguente codice:
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);
});
}
- Nel file
src/lib/firebase/firestore.js, sostituisci la funzionegetRestaurantSnapshotById()con il seguente codice:
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(),
});
});
}
Le modifiche apportate tramite la pagina Database Firestore ora vengono applicate all'app web in tempo reale.
- Crea un commit con il messaggio "Listen for realtime restaurant updates" ed eseguine il push nel tuo repository GitHub.
git add . git commit -m "Listen for realtime restaurant updates" git push - Apri la pagina App Hosting nella console Firebase e attendi il completamento del nuovo lancio.
- Nell'app web, seleziona
> Aggiungi ristoranti di esempio. Se la funzione snapshot è implementata correttamente, i ristoranti vengono visualizzati in tempo reale senza aggiornare la pagina.
8. Salva le recensioni inviate dagli utenti dall'app web
- Nel file
src/lib/firebase/firestore.js, sostituisci la funzioneupdateWithRating()con il seguente codice:
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()),
});
};
Questo codice inserisce un nuovo documento Firestore che rappresenta la nuova recensione. Il codice aggiorna anche il documento Firestore esistente che rappresenta il ristorante con i dati aggiornati relativi al numero di valutazioni e alla valutazione media calcolata.
- Sostituisci la funzione
addReviewToRestaurant()con il seguente codice:
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;
}
}
Implementa un'azione del server Next.js
Un'azione del server Next.js fornisce una comoda API per accedere ai dati del modulo, ad esempio data.get("text") per ottenere il valore di testo dal payload di invio del modulo.
Per utilizzare un'azione del server Next.js per elaborare l'invio del modulo di recensione, segui questi passaggi:
- Nel file
src/components/ReviewDialog.jsx, individua l'attributoactionnell'elemento<form>.
<form
action={handleReviewFormSubmission}
onSubmit={() => {
handleClose();
}}
>
Il valore dell'attributo action fa riferimento a una funzione che implementerai nel passaggio successivo.
- Nel file
src/app/actions.js, sostituisci la funzionehandleReviewFormSubmission()con il seguente codice:
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"),
});
}
Aggiungi recensioni per un ristorante
Hai implementato il supporto per l'invio delle recensioni, quindi ora puoi verificare che le recensioni vengano inserite correttamente in Cloud Firestore.
Per aggiungere una recensione e verificare che sia inserita in Cloud Firestore, segui questi passaggi:
- Crea un commit con il messaggio "Allow users to submit restaurant reviews" ed eseguine il push nel tuo repository GitHub.
git add . git commit -m "Allow users to submit restaurant reviews" git push - Apri la pagina App Hosting nella console Firebase e attendi il completamento del nuovo lancio.
- Aggiorna l'app web e seleziona un ristorante dalla home page.
- Nella pagina del ristorante, fai clic su
. - Seleziona una valutazione a stelle.
- Scrivi una recensione.
- Fai clic su Invia. La tua recensione viene visualizzata in cima all'elenco delle recensioni.
- In Cloud Firestore, cerca nel riquadro Aggiungi documento il documento del ristorante che hai recensito e selezionalo.
- Nel riquadro Avvia raccolta, seleziona Valutazioni.
- Nel riquadro Aggiungi documento, individua il documento da rivedere per verificare che sia stato inserito come previsto.
9. Salva i file caricati dagli utenti dall'app web
In questa sezione, aggiungerai una funzionalità che ti consentirà di sostituire l'immagine associata a un ristorante quando hai eseguito l'accesso. Carichi l'immagine su Firebase Storage e aggiorni l'URL dell'immagine nel documento Cloud Firestore che rappresenta il ristorante.
Per salvare i file caricati dagli utenti dall'app web, segui questi passaggi:
- Nel file
src/components/Restaurant.jsx, osserva il codice che viene eseguito quando l'utente carica un file:
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 });
}
Non sono necessarie modifiche a questa funzione, ma implementerai il comportamento della funzione updateRestaurantImage() nei passaggi successivi.
- Nel file
src/lib/firebase/storage.js, sostituisci le funzioniupdateRestaurantImage()euploadImage()con il seguente codice:
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);
}
La funzione updateRestaurantImageReference() è già implementata per te. Questa funzione aggiorna un documento di un ristorante esistente in Cloud Firestore con un URL dell'immagine aggiornato.
Verifica la funzionalità di caricamento delle immagini
Per verificare che l'immagine venga caricata come previsto, segui questi passaggi:
- Crea un commit con il messaggio "Allow users to change each restaurants' photo" ed eseguine il push nel tuo repository GitHub.
git add . git commit -m "Allow users to change each restaurants' photo" git push - Apri la pagina App Hosting nella console Firebase e attendi il completamento del nuovo lancio.
- Nell'app web, verifica di aver eseguito l'accesso e seleziona un ristorante.
- Fai clic su
e carica un'immagine dal tuo file system. L'immagine lascia l'ambiente locale e viene caricata su Cloud Storage. L'immagine viene visualizzata immediatamente dopo il caricamento. - Vai a Cloud Storage for Firebase.
- Vai alla cartella che rappresenta il ristorante. L'immagine che hai caricato esiste nella cartella.

10. Riassumi le recensioni dei ristoranti con l'AI generativa
In questa sezione, aggiungerai una funzionalità di riepilogo delle recensioni in modo che un utente possa capire rapidamente cosa pensano tutti di un ristorante senza dover leggere ogni recensione.
Archivia una chiave API Gemini in Cloud Secret Manager
- Per utilizzare l'API Gemini, devi avere una chiave API. Visita Google AI Studio e fai clic su Crea chiave API.
- Assegna alla chiave il nome che preferisci. Se il tuo progetto non è elencato in Scegli un progetto importato, fai clic su Importa progetto, seleziona il progetto nell'elenco e poi fai clic su Importa. Infine, selezionalo in Scegli un progetto importato e fai clic su Crea una chiave.
- App Hosting si integra con Cloud Secret Manager per consentirti di archiviare in modo sicuro valori sensibili come le chiavi API:
- In un terminale, esegui il comando per creare un nuovo secret:
firebase apphosting:secrets:set GEMINI_API_KEY- Quando ti viene richiesto il valore secret, copia e incolla la chiave API Gemini da Google AI Studio.
- Quando ti viene chiesto se il nuovo secret è per la produzione o per i test locali, scegli "Produzione".
- Quando ti viene chiesto se vuoi concedere l'accesso in modo che il service account del tuo backend possa accedere al secret, seleziona "Sì".
- Quando ti viene chiesto se il nuovo secret deve essere aggiunto a
apphosting.yaml, inserisciYper accettare.
La tua chiave API Gemini è ora archiviata in modo sicuro in Cloud Secret Manager ed è accessibile al backend di App Hosting.
Implementa il componente di riepilogo delle recensioni
- In
src/components/Reviews/ReviewSummary.jsx, sostituisci la funzioneGeminiSummarycon il seguente codice: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>; } } - Crea un commit con il messaggio "Utilizza l'AI per riassumere le recensioni" ed eseguine il push nel tuo repository GitHub.
git add . git commit -m "Use AI to summarize reviews" git push - Apri la pagina App Hosting nella console Firebase e attendi il completamento del nuovo lancio.
- Apri la pagina di un ristorante. In alto, dovresti vedere un riepilogo di una frase di tutte le recensioni presenti nella pagina.
- Aggiungi una nuova recensione e aggiorna la pagina. Dovresti vedere il riepilogo modificato.
11. Annulla la pubblicazione del sito App Hosting
Dopo aver completato questo codelab, se non intendi continuare a utilizzare l'app, puoi annullarne la pubblicazione per assicurarti che nessuno acceda alle tue risorse Firestore, Storage e Gemini. Puoi ripubblicare i contenuti in qualsiasi momento.
Per annullare la pubblicazione di un sito App Hosting:
- Apri App Hosting nella console Firebase.
- Individua il backend della tua app e fai clic su Visualizza.
- Nella sezione Informazioni sul backend, accanto a Domini, fai clic su Gestisci. Viene caricata la pagina Domini.
- Accanto al tuo dominio, fai clic sull'icona Altro (tre puntini verticali), scegli Disattiva dominio, quindi fai clic su Disattiva per confermare.
12. Conclusione
Complimenti! Hai imparato a utilizzare Firebase per aggiungere funzionalità a un'app Next.js. In particolare, hai utilizzato:
- Firebase App Hosting per creare ed eseguire automaticamente il deployment del codice Next.js ogni volta che esegui il push a un branch configurato.
- Firebase Authentication per attivare la funzionalità di accesso e uscita.
- Cloud Firestore per i dati dei ristoranti e delle recensioni dei ristoranti.
- Cloud Storage for Firebase per le immagini dei ristoranti.