1. Avant de commencer
Dans cet atelier de programmation, vous allez apprendre à intégrer Firebase à une application Web Next.js appelée Friendly Eats, qui est un site Web d'avis sur les restaurants.
L'application Web terminée offre des fonctionnalités utiles qui montrent comment Firebase peut vous aider à créer des applications Next.js. Ces fonctionnalités incluent les suivantes:
- Compilation et déploiement automatiques:cet atelier de programmation utilise Firebase App Hosting pour compiler et déployer automatiquement votre code Next.js chaque fois que vous envoyez un push vers une branche configurée.
- Connexion et déconnexion:l'application Web terminée vous permet de vous connecter avec Google et de vous déconnecter. La connexion et la persistance des utilisateurs sont entièrement gérées par Firebase Authentication.
- Images:l'application Web terminée permet aux utilisateurs connectés d'importer des images de restaurants. Les éléments Image sont stockés dans Cloud Storage for Firebase. Le SDK JavaScript Firebase fournit une URL publique pour les images importées. Cette URL publique est ensuite stockée dans le document du restaurant concerné dans Cloud Firestore.
- Avis:l'application Web terminée permet aux utilisateurs connectés de publier des avis sur les restaurants, qui se composent d'une note et d'un message textuel. Les informations sur les avis sont stockées dans Cloud Firestore.
- Filtres:l'application Web terminée permet aux utilisateurs connectés de filtrer la liste des restaurants en fonction de la catégorie, de l'emplacement et du prix. Vous pouvez également personnaliser la méthode de tri utilisée. Les données sont accessibles depuis Cloud Firestore, et les requêtes Firestore sont appliquées en fonction des filtres utilisés.
Prérequis
- Un compte GitHub
- Connaissances de Next.js et JavaScript
Points abordés
- Utiliser Firebase avec le routeur d'application Next.js et le rendu côté serveur
- Comment conserver des images dans Cloud Storage for Firebase
- Lire et écrire des données dans une base de données Cloud Firestore
- Utiliser la connexion avec Google avec le SDK JavaScript Firebase
Prérequis
- Git
- Une version stable récente de Node.js
- Un navigateur de votre choix, comme Google Chrome
- Un environnement de développement avec un éditeur de code et un terminal
- Un compte Google pour créer et gérer votre projet Firebase
- La possibilité de passer votre projet Firebase au forfait Blaze
2. Configurer votre environnement de développement et votre dépôt GitHub
Cet atelier de programmation fournit le code de démarrage de l'application et s'appuie sur la CLI Firebase.
Créer un dépôt GitHub
Le code source de l'atelier de programmation est disponible à l'adresse https://github.com/firebase/friendlyeats-web. Le dépôt contient des exemples de projets adaptés à différentes plates-formes. Cependant, cet atelier de programmation n'utilise que le répertoire nextjs-start
. Notez les répertoires suivants:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Copiez le dossier nextjs-start
dans votre propre dépôt:
- À l'aide d'un terminal, créez un dossier sur votre ordinateur et accédez au nouveau répertoire:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web
- Utilisez le package npm giget pour ne récupérer que le dossier
nextjs-start
:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- Suivez les modifications localement avec git:
git init git commit -a -m "codelab starting point" git branch -M main
- Créez un dépôt GitHub: https://github.com/new. Vous pouvez lui donner le nom de votre choix.
- GitHub vous fournira une nouvelle URL de dépôt qui ressemble à
https://github.com/
ou/ .git git@github.com:
. Copiez cette URL./ .git
- GitHub vous fournira une nouvelle URL de dépôt qui ressemble à
- Transférez les modifications locales vers votre nouveau dépôt GitHub. Exécutez la commande suivante en remplaçant l'espace réservé
par l'URL de votre dépôt.git remote add origin <your-repository-url> git push -u origin main
- Le code de démarrage devrait maintenant s'afficher dans votre dépôt GitHub.
Installer ou mettre à jour la CLI Firebase
Exécutez la commande suivante pour vérifier que la CLI Firebase est installée et qu'elle est de version 13.9.0 ou ultérieure:
firebase --version
Si une version antérieure s'affiche ou si la CLI Firebase n'est pas installée, exécutez la commande d'installation:
npm install -g firebase-tools@latest
Si vous ne parvenez pas à installer la CLI Firebase en raison d'erreurs d'autorisation, consultez la documentation npm ou utilisez une autre option d'installation.
Se connecter à Firebase
- Exécutez la commande suivante pour vous connecter à la CLI Firebase:
firebase login
- Selon que vous souhaitez que Firebase collecte des données, saisissez
Y
ouN
. - Dans votre navigateur, sélectionnez votre compte Google, puis cliquez sur Autoriser.
3. Configurer votre projet Firebase
Dans cette section, vous allez configurer un projet Firebase et y associer une application Web Firebase. Vous allez également configurer les services Firebase utilisés par l'application Web exemple.
Créer un projet Firebase
- Dans la console Firebase, cliquez sur Ajouter un projet.
- Dans la zone de texte Enter your project name (Saisissez le nom de votre projet), saisissez
FriendlyEats Codelab
(ou le nom de votre choix), puis cliquez sur Continue (Continuer). - Dans la fenêtre modale Confirm Firebase billing plan (Confirmer le mode de facturation Firebase), vérifiez que le forfait est Blaze, puis cliquez sur Confirm plan (Confirmer le mode de facturation).
- Pour cet atelier de programmation, vous n'avez pas besoin de Google Analytics. Désactivez donc l'option Activer Google Analytics pour ce projet.
- Cliquez sur Create Project (Créer un projet).
- Attendez que votre projet soit provisionné, puis cliquez sur Continuer.
- Dans votre projet Firebase, accédez à Paramètres du projet. Notez l'ID de votre projet, car vous en aurez besoin plus tard. Cet identifiant unique permet d'identifier votre projet (par exemple, dans la CLI Firebase).
Passer à un forfait Firebase supérieur
Pour utiliser Firebase App Hosting et Cloud Storage for Firebase, votre projet Firebase doit être associé au forfait Blaze avec paiement à l'usage, ce qui signifie qu'il est associé à un compte de facturation Cloud.
- Un compte de facturation Cloud nécessite un mode de paiement, comme une carte de crédit.
- Si vous débutez avec Firebase et Google Cloud, vérifiez si vous pouvez bénéficier d'un crédit de 300$et d'un compte de facturation Cloud en essai sans frais.
- Si vous suivez cet atelier de programmation dans le cadre d'un événement, demandez à l'organisateur s'il existe des crédits Cloud disponibles.
Pour passer à la formule Blaze, procédez comme suit:
- Dans la console Firebase, sélectionnez l'option Mettre à niveau votre forfait.
- Sélectionnez le forfait Blaze. Suivez les instructions à l'écran pour associer un compte de facturation Cloud à votre projet.
Si vous avez dû créer un compte de facturation Cloud dans le cadre de cette migration, vous devrez peut-être revenir au flux de migration dans la console Firebase pour la terminer.
Ajouter une application Web à votre projet Firebase
- Accédez à la vue d'ensemble du projet dans votre projet Firebase, puis cliquez sur Web.
Si des applications sont déjà enregistrées dans votre projet, cliquez sur Ajouter une application pour afficher l'icône Web. - Dans la zone de texte App nickname (Pseudo de l'application), saisissez un pseudo d'application facile à retenir, par exemple
My Next.js app
. - Ne cochez pas la case Configurer également Firebase Hosting pour cette application.
- Cliquez sur Enregistrer l'application > Suivant > Suivant > Accéder à la console.
Configurer les services Firebase dans la console Firebase
Configurer l'authentification
- Dans la console Firebase, accédez à Authentification.
- Cliquez sur Commencer.
- Dans la colonne Fournisseurs supplémentaires, cliquez sur Google > Activer.
- Dans la zone de texte Nom public du projet, saisissez un nom facile à retenir, par exemple
My Next.js app
. - Dans la liste déroulante Adresse e-mail d'assistance pour le projet, sélectionnez votre adresse e-mail.
- Cliquez sur Enregistrer.
Configurer Cloud Firestore
- Dans le panneau de gauche de la console Firebase, développez Build (Compilation), puis sélectionnez Firestore database (Base de données Firestore).
- Cliquez sur Créer une base de données.
- Laissez le champ Database ID (ID de la base de données) défini sur
(default)
. - Sélectionnez un emplacement pour votre base de données, puis cliquez sur Suivant.
Pour une application réelle, choisissez un emplacement proche de vos utilisateurs. - Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
Plus tard dans cet atelier de programmation, vous ajouterez des règles de sécurité pour sécuriser vos données. Ne distribuez pas ni n'exposez pas publiquement une application sans ajouter de règles de sécurité à votre base de données. - Cliquez sur Créer.
Configurer Cloud Storage for Firebase
- Dans le panneau de gauche de la console Firebase, développez Build (Compilation), puis sélectionnez Storage (Stockage).
- Cliquez sur Commencer.
- Sélectionnez un emplacement pour votre bucket Storage par défaut.
Les buckets dansUS-WEST1
,US-CENTRAL1
etUS-EAST1
peuvent profiter du niveau"Toujours sans frais" pour Google Cloud Storage. Les buckets situés dans toutes les autres zones géographiques sont soumis aux tarifs et à l'utilisation de Google Cloud Storage. - Cliquez sur Démarrer en mode test. Lisez la clause de non-responsabilité concernant les règles de sécurité.
Plus tard dans cet atelier de programmation, vous ajouterez des règles de sécurité pour sécuriser vos données. Ne distribuez pas ni n'exposez pas publiquement une application sans ajouter de règles de sécurité à votre bucket Storage. - Cliquez sur Créer.
4. Examiner le code de démarrage
Dans cette section, vous allez examiner quelques éléments du code de démarrage de l'application auxquels vous allez ajouter des fonctionnalités dans cet atelier de programmation.
Structure des dossiers et des fichiers
Le tableau suivant présente la structure des dossiers et des fichiers de l'application:
Dossiers et fichiers | Description |
| Composants React pour les filtres, les en-têtes, les informations sur les restaurants et les avis |
| Fonctions utilitaires qui ne sont pas nécessairement liées à React ou Next.js |
| Code et configuration Firebase spécifiques |
| Éléments statiques de l'application Web, comme les icônes |
| Routage avec le routeur d'application Next.js |
| Un gestionnaire de routage d'API |
| Dépendances du projet avec npm |
| Configuration spécifique à Next.js (les actions du serveur sont activées) |
| Configuration du service de langage JavaScript |
Composants du serveur et du client
Il s'agit d'une application Web Next.js qui utilise le routeur d'application. L'affichage côté serveur est utilisé dans l'ensemble de l'application. Par exemple, le fichier src/app/page.js
est un composant serveur responsable de la page principale. Le fichier src/components/RestaurantListings.jsx
est un composant client indiqué par la directive "use client"
au début du fichier.
Instructions d'importation
Vous pouvez remarquer des instructions d'importation telles que les suivantes:
import RatingPicker from "@/src/components/RatingPicker.jsx";
L'application utilise le symbole @
pour éviter les chemins d'importation relatifs peu pratiques et est rendue possible par les alias de chemin d'accès.
API spécifiques à Firebase
Tout le code de l'API Firebase est encapsulé dans le répertoire src/lib/firebase
. Les composants React individuels importent ensuite les fonctions encapsulées à partir du répertoire src/lib/firebase
, plutôt que d'importer directement les fonctions Firebase.
Données fictives
Les données fictives sur les restaurants et les avis sont contenues dans le fichier src/lib/randomData.js
. Les données de ce fichier sont assemblées dans le code du fichier src/lib/fakeRestaurants.js
.
5. Créer un backend App Hosting
Dans cette section, vous allez configurer un backend App Hosting pour surveiller une branche de votre dépôt Git.
À la fin de cette section, vous aurez un backend App Hosting connecté à votre dépôt GitHub. Il recompilera et déploiera automatiquement une nouvelle version de votre application chaque fois que vous enverrez un nouveau commit dans votre branche main
.
Déployer des règles de sécurité
Le code contient déjà des ensembles de règles de sécurité pour Firestore et Cloud Storage for Firebase. Une fois les règles de sécurité déployées, les données de votre base de données et de votre bucket sont mieux protégées contre les utilisations abusives.
- Dans votre terminal, configurez la CLI pour qu'elle utilise le projet Firebase que vous avez créé précédemment:
firebase use --add
Lorsque vous êtes invité à saisir un alias, saisissezfriendlyeats-codelab
. - Pour déployer ces règles de sécurité, exécutez la commande suivante dans votre terminal:
firebase deploy --only firestore:rules,storage
- Si vous êtes invité à répondre à la question:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"
, appuyez surEnter
pour sélectionner Oui.
Ajouter votre configuration Firebase au code de votre application Web
- Dans la console Firebase, accédez à vos Paramètres du projet.
- Dans le volet Configuration et configuration du SDK, cliquez sur "Ajouter une application", puis sur l'icône des crochets de code
pour enregistrer une nouvelle application Web.
- À la fin du flux de création d'une application Web, copiez la variable
firebaseConfig
, ainsi que ses propriétés et leurs valeurs. - Ouvrez le fichier
apphosting.yaml
dans votre éditeur de code, puis remplacez les valeurs des variables d'environnement par les valeurs de configuration de la console Firebase. - Dans le fichier, remplacez les propriétés existantes par celles que vous avez copiées.
- Enregistrez le fichier.
Créer un backend
- Accédez à la page Hébergement d'applications dans la console Firebase:
- Cliquez sur "Commencer" pour lancer le flux de création du backend. Configurez votre backend comme suit:
- Suivez les instructions de la première étape pour connecter le dépôt GitHub que vous avez créé précédemment.
- Définissez les paramètres de déploiement:
- Laisser le répertoire racine tel quel (
/
) - Définissez la branche en direct sur
main
. - Activer les déploiements automatiques
- Laisser le répertoire racine tel quel (
- Nommez votre backend
friendlyeats-codelab
. - Dans "Créer ou associer une application Web Firebase", sélectionnez l'application Web que vous avez configurée précédemment dans le menu déroulant "Sélectionner une application Web Firebase existante".
- Cliquez sur "Terminer et déployer". Après un moment, vous serez redirigé vers une nouvelle page où vous pourrez consulter l'état de votre nouveau backend d'hébergement d'applications.
- Une fois le déploiement terminé, cliquez sur votre domaine sans frais sous "domaines". La propagation du DNS peut prendre quelques minutes.
Vous avez déployé l'application Web initiale. Chaque fois que vous envoyez un nouveau commit vers la branche main
de votre dépôt GitHub, une nouvelle compilation et un nouveau déploiement commencent dans la console Firebase. Votre site est automatiquement mis à jour une fois le déploiement terminé.
6. Ajouter une authentification à l'application Web
Dans cette section, vous allez ajouter une authentification à l'application Web afin de pouvoir vous y connecter.
Implémenter les fonctions de connexion et de déconnexion
- Dans le fichier
src/lib/firebase/auth.js
, remplacez les fonctionsonAuthStateChanged
,signInWithGoogle
etsignOut
par le code suivant:
export function onAuthStateChanged(cb) {
return _onAuthStateChanged(auth, cb);
}
export async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
try {
await signInWithPopup(auth, provider);
} catch (error) {
console.error("Error signing in with Google", error);
}
}
export async function signOut() {
try {
return auth.signOut();
} catch (error) {
console.error("Error signing out with Google", error);
}
}
Ce code utilise les API Firebase suivantes:
API Firebase | Description |
Crée une instance de fournisseur d'authentification Google. | |
Lance un flux d'authentification basé sur une boîte de dialogue. | |
Déconnecte l'utilisateur. |
Dans le fichier src/components/Header.jsx
, le code appelle déjà les fonctions signInWithGoogle
et signOut
.
- Créez un commit avec le message "Ajout de l'authentification Google" et transférez-le vers votre dépôt GitHub. 1. Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Dans l'application Web, actualisez la page, puis cliquez sur Se connecter avec Google. L'application Web ne s'actualise pas. Il est donc difficile de savoir si la connexion a réussi.
Envoyer l'état d'authentification au serveur
Pour transmettre l'état d'authentification au serveur, nous allons utiliser un service worker. Remplacez les fonctions fetchWithFirebaseHeaders
et getAuthIdToken
par le code suivant:
async function fetchWithFirebaseHeaders(request) {
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const installations = getInstallations(app);
const headers = new Headers(request.headers);
const [authIdToken, installationToken] = await Promise.all([
getAuthIdToken(auth),
getToken(installations),
]);
headers.append("Firebase-Instance-ID-Token", installationToken);
if (authIdToken) headers.append("Authorization", `Bearer ${authIdToken}`);
const newRequest = new Request(request, { headers });
return await fetch(newRequest);
}
async function getAuthIdToken(auth) {
await auth.authStateReady();
if (!auth.currentUser) return;
return await getIdToken(auth.currentUser);
}
Lire l'état d'authentification sur le serveur
Nous allons utiliser FirebaseServerApp pour refléter l'état d'authentification du client sur le serveur.
Ouvrez src/lib/firebase/serverApp.js
et remplacez la fonction getAuthenticatedAppForUser
:
export async function getAuthenticatedAppForUser() {
const idToken = headers().get("Authorization")?.split("Bearer ")[1];
console.log('firebaseConfig', JSON.stringify(firebaseConfig));
const firebaseServerApp = initializeServerApp(
firebaseConfig,
idToken
? {
authIdToken: idToken,
}
: {}
);
const auth = getAuth(firebaseServerApp);
await auth.authStateReady();
return { firebaseServerApp, currentUser: auth.currentUser };
}
S'abonner aux modifications liées à l'authentification
Pour vous abonner aux modifications d'authentification, procédez comme suit:
- Accédez au fichier
src/components/Header.jsx
. - Remplacez la fonction
useUserSession
par le code suivant:
function useUserSession(initialUser) {
// The initialUser comes from the server via a server component
const [user, setUser] = useState(initialUser);
const router = useRouter();
// Register the service worker that sends auth state back to server
// The service worker is built with npm run build-service-worker
useEffect(() => {
if ("serviceWorker" in navigator) {
const serializedFirebaseConfig = encodeURIComponent(JSON.stringify(firebaseConfig));
const serviceWorkerUrl = `/auth-service-worker.js?firebaseConfig=${serializedFirebaseConfig}`
navigator.serviceWorker
.register(serviceWorkerUrl)
.then((registration) => console.log("scope is: ", registration.scope));
}
}, []);
useEffect(() => {
const unsubscribe = onAuthStateChanged((authUser) => {
setUser(authUser)
})
return () => unsubscribe()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
onAuthStateChanged((authUser) => {
if (user === undefined) return
// refresh when user changed to ease testing
if (user?.email !== authUser?.email) {
router.refresh()
}
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user])
return user;
}
Ce code utilise un hook d'état React pour mettre à jour l'utilisateur lorsque la fonction onAuthStateChanged
spécifie qu'il y a un changement de l'état d'authentification.
Vérifier les modifications
La mise en page racine du fichier src/app/layout.js
affiche l'en-tête et transmet l'utilisateur, le cas échéant, en tant qu'accessoire.
<Header initialUser={currentUser?.toJSON()} />
Cela signifie que le composant <Header>
affiche les données utilisateur, le cas échéant, pendant l'exécution du serveur. Si des mises à jour d'authentification sont effectuées pendant le cycle de vie de la page après le chargement initial, le gestionnaire onAuthStateChanged
les gère.
Il est maintenant temps de déployer une nouvelle version et de vérifier ce que vous avez créé.
- Créez un commit avec le message "Afficher l'état de connexion", puis transférez-le vers votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Vérifiez le nouveau comportement d'authentification:
- Dans votre navigateur, actualisez l'application Web. Votre nom à afficher s'affiche dans l'en-tête.
- Déconnectez-vous, puis reconnectez-vous. La page est mise à jour en temps réel sans actualisation. Vous pouvez répéter cette étape avec différents utilisateurs.
- Facultatif: Effectuez un clic droit sur l'application Web, sélectionnez Afficher le code source de la page, puis recherchez le nom à afficher. Il apparaît dans la source HTML brute renvoyée par le serveur.
7. Afficher les informations sur un restaurant
L'application Web inclut des données fictives pour les restaurants et les avis.
Ajouter un ou plusieurs restaurants
Pour insérer des données fictives sur des restaurants dans votre base de données Cloud Firestore locale, procédez comme suit:
- Dans l'application Web, sélectionnez > Ajouter des exemples de restaurants.
- Dans la console Firebase, sur la page Base de données Firestore, sélectionnez restaurants. Vous voyez les documents de premier niveau de la collection de restaurants, chacun représentant un restaurant.
- Cliquez sur quelques documents pour explorer les propriétés d'un document "restaurant".
Afficher la liste des restaurants
Votre base de données Cloud Firestore contient désormais des restaurants que l'application Web Next.js peut afficher.
Pour définir le code de récupération des données, procédez comme suit:
- Dans le fichier
src/app/page.js
, recherchez le composant serveur<Home />
et examinez l'appel de la fonctiongetRestaurants
, qui récupère une liste de restaurants au moment de l'exécution du serveur. Vous allez implémenter la fonctiongetRestaurants
en suivant les étapes ci-dessous. - Dans le fichier
src/lib/firebase/firestore.js
, remplacez les fonctionsapplyQueryFilters
etgetRestaurants
par le code suivant:
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(),
};
});
}
- Créez un commit avec le message "Lire la liste des restaurants à partir de Firestore", puis transférez-le vers votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Dans l'application Web, actualisez la page. Les images des restaurants s'affichent sous forme de cartes sur la page.
Vérifier que les fiches de restaurant se chargent au moment de l'exécution du serveur
Avec le framework Next.js, il peut être difficile de savoir quand les données sont chargées au moment de l'exécution du serveur ou côté client.
Pour vérifier que les fiches de restaurant se chargent au moment de l'exécution du serveur, procédez comme suit:
- Dans l'application Web, ouvrez les outils pour les développeurs et désactivez JavaScript.
- Actualisez l'application Web. Les fiches de restaurant continuent de s'afficher. Les informations sur le restaurant sont renvoyées dans la réponse du serveur. Lorsque JavaScript est activé, les informations sur le restaurant sont hydratées via le code JavaScript côté client.
- Dans les outils de développement, réactivez JavaScript.
Écouter les mises à jour des restaurants avec les écouteurs d'instantanés Cloud Firestore
Dans la section précédente, vous avez vu comment l'ensemble initial de restaurants était chargé à partir du fichier src/app/page.js
. Le fichier src/app/page.js
est un composant serveur et est affiché sur le serveur, y compris le code de récupération des données Firebase.
Le fichier src/components/RestaurantListings.jsx
est un composant client et peut être configuré pour hydrater le balisage rendu par le serveur.
Pour configurer le fichier src/components/RestaurantListings.jsx
afin d'hydrater le balisage rendu par le serveur, procédez comme suit:
- Dans le fichier
src/components/RestaurantListings.jsx
, examinez le code suivant, qui est déjà écrit pour vous:
useEffect(() => {
const unsubscribe = getRestaurantsSnapshot(data => {
setRestaurants(data);
}, filters);
return () => {
unsubscribe();
};
}, [filters]);
Ce code appelle la fonction getRestaurantsSnapshot()
, qui est semblable à la fonction getRestaurants()
que vous avez implémentée à une étape précédente. Toutefois, cette fonction d'instantané fournit un mécanisme de rappel afin que le rappel soit appelé chaque fois qu'une modification est apportée à la collection des restaurants.
- Dans le fichier
src/lib/firebase/firestore.js
, remplacez la fonctiongetRestaurantsSnapshot()
par le code suivant:
export function getRestaurantsSnapshot(cb, filters = {}) {
if (typeof cb !== "function") {
console.log("Error: The callback parameter is not a function");
return;
}
let q = query(collection(db, "restaurants"));
q = applyQueryFilters(q, filters);
const unsubscribe = onSnapshot(q, querySnapshot => {
const results = querySnapshot.docs.map(doc => {
return {
id: doc.id,
...doc.data(),
// Only plain objects can be passed to Client Components from Server Components
timestamp: doc.data().timestamp.toDate(),
};
});
cb(results);
});
return unsubscribe;
}
Les modifications apportées via la page Base de données Firestore sont désormais répercutées en temps réel dans l'application Web.
- Créez un commit avec le message "Écouter les mises à jour des restaurants en temps réel" et transférez-le vers votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Dans l'application Web, sélectionnez > Ajouter des exemples de restaurants. Si votre fonction d'instantané est implémentée correctement, les restaurants s'affichent en temps réel sans actualisation de la page.
8. Enregistrer les avis envoyés par les utilisateurs depuis l'application Web
- Dans le fichier
src/lib/firebase/firestore.js
, remplacez la fonctionupdateWithRating()
par le code suivant:
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()),
});
};
Ce code insère un nouveau document Firestore représentant le nouvel avis. Le code met également à jour le document Firestore existant qui représente le restaurant avec des chiffres mis à jour pour le nombre de notes et la note moyenne calculée.
- Remplacez la fonction
addReviewToRestaurant()
par le code suivant:
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;
}
}
Implémenter une action de serveur Next.js
Une action de serveur Next.js fournit une API pratique pour accéder aux données du formulaire, comme data.get("text")
pour obtenir la valeur textuelle de la charge utile d'envoi du formulaire.
Pour utiliser une action de serveur Next.js pour traiter l'envoi du formulaire d'avis, procédez comme suit:
- Dans le fichier
src/components/ReviewDialog.jsx
, recherchez l'attributaction
dans l'élément<form>
.
<form action={handleReviewFormSubmission}>
La valeur de l'attribut action
fait référence à une fonction que vous implémenterez à l'étape suivante.
- Dans le fichier
src/app/actions.js
, remplacez la fonctionhandleReviewFormSubmission()
par le code suivant:
// 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"),
});
}
Ajouter des avis pour un restaurant
Vous avez implémenté la possibilité d'envoyer des avis. Vous pouvez maintenant vérifier que vos avis sont correctement insérés dans Cloud Firestore.
Pour ajouter un avis et vérifier qu'il est inséré dans Cloud Firestore, procédez comme suit:
- Créez un commit avec le message "Permettre aux utilisateurs d'envoyer des avis sur les restaurants", puis transférez-le vers votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Actualisez l'application Web, puis sélectionnez un restaurant sur la page d'accueil.
- Sur la page du restaurant, cliquez sur .
- Sélectionnez une note.
- Rédigez un avis.
- Cliquez sur Envoyer. Votre avis s'affiche en haut de la liste.
- Dans Cloud Firestore, recherchez le document du restaurant que vous avez évalué dans le volet Ajouter un document, puis sélectionnez-le.
- Dans le volet Start collection (Commencer une collection), sélectionnez ratings (Avis).
- Dans le volet Ajouter un document, recherchez le document à examiner pour vérifier qu'il a été inséré comme prévu.
9. Enregistrer les fichiers importés par les utilisateurs depuis l'application Web
Dans cette section, vous allez ajouter une fonctionnalité qui vous permettra de remplacer l'image associée à un restaurant lorsque vous êtes connecté. Vous importez l'image dans Firebase Storage et mettez à jour l'URL de l'image dans le document Cloud Firestore représentant le restaurant.
Pour enregistrer les fichiers importés par les utilisateurs depuis l'application Web, procédez comme suit:
- Dans le fichier
src/components/Restaurant.jsx
, observez le code qui s'exécute lorsque l'utilisateur importe un fichier:
async function handleRestaurantImage(target) {
const image = target.files ? target.files[0] : null;
if (!image) {
return;
}
const imageURL = await updateRestaurantImage(id, image);
setRestaurant({ ...restaurant, photo: imageURL });
}
Aucune modification n'est requise, mais vous implémentez le comportement de la fonction updateRestaurantImage()
dans les étapes suivantes.
- Dans le fichier
src/lib/firebase/storage.js
, remplacez les fonctionsupdateRestaurantImage()
etuploadImage()
par le code suivant:
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 fonction updateRestaurantImageReference()
est déjà implémentée pour vous. Cette fonction met à jour un document de restaurant existant dans Cloud Firestore avec une URL d'image mise à jour.
Vérifier la fonctionnalité d'importation d'images
Pour vérifier que l'image est importée comme prévu, procédez comme suit:
- Créez un commit avec le message "Permettre aux utilisateurs de modifier la photo de chaque restaurant", puis transférez-le vers votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Dans l'application Web, vérifiez que vous êtes connecté et sélectionnez un restaurant.
- Cliquez sur , puis importez une image depuis votre système de fichiers. Votre image quitte votre environnement local et est importée dans Cloud Storage. L'image apparaît immédiatement après sa mise en ligne.
- Accédez à Cloud Storage for Firebase.
- Accédez au dossier représentant le restaurant. L'image que vous avez importée existe dans le dossier.
10. Résumer les avis sur un restaurant avec l'IA générative
Dans cette section, vous allez ajouter une fonctionnalité de résumé des avis afin qu'un utilisateur puisse rapidement comprendre ce que tout le monde pense d'un restaurant sans avoir à lire tous les avis.
Stocker une clé API Gemini dans Cloud Secret Manager
- Pour utiliser l'API Gemini, vous avez besoin d'une clé API. Créez une clé dans Google AI Studio.
- App Hosting s'intègre à Cloud Secret Manager pour vous permettre de stocker des valeurs sensibles telles que des clés API de manière sécurisée:
- Dans un terminal, exécutez la commande suivante pour créer un secret:
firebase apphosting:secrets:set gemini-api-key
- Lorsque vous êtes invité à saisir la valeur secrète, copiez et collez votre clé API Gemini depuis Google AI Studio.
- Lorsque vous êtes invité à ajouter le nouveau secret à
apphosting.yaml
, saisissezY
pour accepter.
Votre clé API Gemini est désormais stockée de manière sécurisée dans Cloud Secret Manager et est accessible à votre backend d'hébergement d'applications.
Implémenter le composant de résumé des avis
- Dans
src/components/Reviews/ReviewSummary.jsx
, remplacez la fonctionGeminiSummary
par le code suivant:export async function GeminiSummary({ restaurantId }) { const { firebaseServerApp } = await getAuthenticatedAppForUser(); const reviews = await getReviewsByRestaurantId( getFirestore(firebaseServerApp), restaurantId ); const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY); const model = genAI.getGenerativeModel({ model: "gemini-pro"}); const reviewSeparator = "@"; const prompt = ` Based on the following restaurant reviews, where each review is separated by a '${reviewSeparator}' character, create a one-sentence summary of what people think of the restaurant. Here are the reviews: ${reviews.map(review => review.text).join(reviewSeparator)} `; try { const result = await model.generateContent(prompt); const response = await result.response; const text = response.text(); return ( <div className="restaurant__review_summary"> <p>{text}</p> <p>✨ Summarized with Gemini</p> </div> ); } catch (e) { console.error(e); return <p>Error contacting Gemini</p>; } }
- Créez un commit avec le message "Utiliser l'IA pour résumer les avis" et déployez-le dans votre dépôt GitHub.
- Ouvrez la page Hébergement d'applications dans la console Firebase, puis attendez que le déploiement soit terminé.
- Ouvrez la page d'un restaurant. En haut de la page, vous devriez voir un résumé en une phrase de tous les avis de la page.
- Ajoutez un avis et actualisez la page. Le résumé devrait changer.
11. Conclusion
Félicitations ! Vous avez appris à utiliser Firebase pour ajouter des fonctionnalités à une application Next.js. Plus précisément, vous avez utilisé les éléments suivants:
- Firebase App Hosting pour compiler et déployer automatiquement votre code Next.js chaque fois que vous envoyez un push vers une branche configurée.
- Firebase Authentication pour activer les fonctionnalités de connexion et de déconnexion.
- Cloud Firestore pour les données sur les restaurants et les avis sur les restaurants
- Cloud Storage for Firebase pour les images des restaurants.