1. Sebelum memulai
Dalam codelab ini, Anda akan mempelajari cara mengintegrasikan Firebase dengan aplikasi web Next.js yang disebut Friendly Eats, yaitu situs yang menyediakan ulasan restoran.
Aplikasi web yang sudah selesai menawarkan fitur berguna yang menunjukkan bagaimana Firebase dapat membantu Anda membangun aplikasi Next.js. Fitur tersebut mencakup:
- Build dan deploy otomatis: Codelab ini menggunakan Firebase App Hosting untuk secara otomatis mem-build dan men-deploy kode Next.js setiap kali Anda mengirim ke cabang yang dikonfigurasi.
- Login dan logout: Aplikasi web yang telah selesai memungkinkan Anda login dengan Google serta logout. Login dan persistensi pengguna dikelola sepenuhnya melalui Firebase Authentication.
- Gambar: Aplikasi web yang sudah selesai memungkinkan pengguna yang login mengupload gambar restoran. Aset gambar disimpan di Cloud Storage for Firebase. Firebase JavaScript SDK menyediakan URL publik untuk gambar yang diupload. URL publik ini kemudian disimpan di dokumen restoran yang relevan di Cloud Firestore.
- Ulasan: Dengan aplikasi web yang sudah selesai, pengguna yang login dapat memposting ulasan tentang restoran yang terdiri dari rating bintang dan pesan berbasis teks. Informasi ulasan disimpan di Cloud Firestore.
- Filter: Dengan aplikasi web yang sudah selesai, pengguna yang login dapat memfilter daftar restoran berdasarkan kategori, lokasi, dan harga. Anda juga dapat menyesuaikan metode pengurutan yang digunakan. Data diakses dari Cloud Firestore, dan kueri Firestore diterapkan berdasarkan filter yang digunakan.
Prasyarat
- Akun GitHub
- Pengetahuan tentang Next.js dan JavaScript
Yang akan Anda pelajari
- Cara menggunakan Firebase dengan Router Aplikasi Next.js dan rendering sisi server.
- Cara mempertahankan gambar di Cloud Storage for Firebase.
- Cara membaca dan menulis data di database Cloud Firestore.
- Cara menggunakan login dengan Google menggunakan Firebase JavaScript SDK.
Yang Anda butuhkan
- Git
- Node.js versi stabil terbaru
- Browser pilihan Anda, seperti Google Chrome
- Lingkungan pengembangan dengan editor kode dan terminal
- Akun Google untuk pembuatan dan pengelolaan project Firebase Anda
- Kemampuan untuk mengupgrade project Firebase ke paket harga Blaze
2. Menyiapkan lingkungan pengembangan dan repositori GitHub
Codelab ini menyediakan codebase awal aplikasi dan mengandalkan Firebase CLI.
Membuat repositori GitHub
Sumber codelab dapat ditemukan di https://github.com/firebase/friendlyeats-web. Repositori berisi project contoh untuk beberapa platform. Namun, codelab ini hanya menggunakan direktori nextjs-start
. Perhatikan direktori berikut:
* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.
Salin folder nextjs-start
ke repositori Anda sendiri:
- Dengan menggunakan terminal, buat folder baru di komputer dan beralih ke direktori baru:
mkdir codelab-friendlyeats-web cd codelab-friendlyeats-web
- Gunakan paket npm giget untuk mengambil folder
nextjs-start
saja:npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
- Lacak perubahan secara lokal dengan git:
git init git commit -a -m "codelab starting point" git branch -M main
- Buat repositori GitHub baru: https://github.com/new. Beri nama apa pun yang Anda inginkan.
- GitHub akan memberi Anda URL repositori baru yang terlihat seperti
https://github.com/
atau/ .git git@github.com:
. Salin URL ini./ .git
- GitHub akan memberi Anda URL repositori baru yang terlihat seperti
- Kirim perubahan lokal ke repositori GitHub baru Anda. Jalankan perintah berikut, dengan mengganti URL repositori Anda untuk placeholder
.git remote add origin <your-repository-url> git push -u origin main
- Sekarang Anda akan melihat kode awal di repositori GitHub.
Menginstal atau mengupdate Firebase CLI
Jalankan perintah berikut untuk memverifikasi bahwa Anda telah menginstal Firebase CLI dan menggunakan versi v13.9.0 atau yang lebih tinggi:
firebase --version
Jika Anda melihat versi yang lebih rendah atau belum menginstal Firebase CLI, jalankan perintah penginstalan:
npm install -g firebase-tools@latest
Jika Anda tidak dapat menginstal Firebase CLI karena error izin, lihat dokumentasi npm atau gunakan opsi penginstalan lainnya.
Login ke Firebase
- Jalankan perintah berikut untuk login ke Firebase CLI:
firebase login
- Bergantung pada apakah Anda ingin Firebase mengumpulkan data, masukkan
Y
atauN
. - Di browser, pilih akun Google Anda, lalu klik Allow.
3. Menyiapkan project Firebase
Di bagian ini, Anda akan menyiapkan project Firebase dan mengaitkan aplikasi web Firebase dengan project tersebut. Anda juga akan menyiapkan layanan Firebase yang digunakan oleh aplikasi web contoh.
Membuat project Firebase
- Di Firebase console, klik Tambahkan project.
- Di kotak teks Enter your project name, masukkan
FriendlyEats Codelab
(atau nama project pilihan Anda), lalu klik Continue. - Di modal Konfirmasi paket penagihan Firebase, pastikan paketnya adalah Blaze, lalu klik Konfirmasi paket
- Untuk codelab ini, Anda tidak memerlukan Google Analytics. Oleh karena itu, nonaktifkan opsi Enable Google Analytics for this project.
- Klik Create project.
- Tunggu hingga project Anda disediakan, lalu klik Continue.
- Di project Firebase Anda, buka Project Settings. Catat project ID Anda karena Anda akan memerlukannya nanti. ID unik ini adalah cara project Anda diidentifikasi (misalnya, di Firebase CLI).
Mengupgrade paket harga Firebase Anda
Untuk menggunakan Firebase App Hosting dan Cloud Storage for Firebase, project Firebase Anda harus menggunakan paket harga bayar sesuai penggunaan (Blaze), yang berarti project tersebut ditautkan ke akun Penagihan Cloud.
- Akun Penagihan Cloud memerlukan metode pembayaran, seperti kartu kredit.
- Jika Anda baru menggunakan Firebase dan Google Cloud, periksa apakah Anda memenuhi syarat untuk mendapatkan kredit sebesar $300 dan akun Penagihan Cloud Uji Coba Gratis.
- Jika Anda melakukan codelab ini sebagai bagian dari acara, tanyakan kepada penyelenggara apakah ada kredit Cloud yang tersedia.
Untuk mengupgrade project Anda ke paket Blaze, ikuti langkah-langkah berikut:
- Di Firebase console, pilih upgrade your plan.
- Pilih paket Blaze. Ikuti petunjuk di layar untuk menautkan akun Penagihan Cloud ke project Anda.
Jika perlu membuat akun Penagihan Cloud sebagai bagian dari upgrade ini, Anda mungkin perlu kembali ke alur upgrade di Firebase console untuk menyelesaikan upgrade.
Menambahkan aplikasi web ke project Firebase
- Buka Project overview di project Firebase Anda, lalu klik Web.
Jika Anda sudah memiliki aplikasi yang terdaftar di project, klik Add app untuk melihat ikon Web. - Di kotak teks App nickname, masukkan nama panggilan aplikasi yang mudah diingat, seperti
My Next.js app
. - Jangan centang kotak Also set up Firebase Hosting for this app.
- Klik Register app > Next > Next > Continue to konsol.
Menyiapkan layanan Firebase di Firebase console
Menyiapkan Authentication
- Di Firebase console, buka Authentication.
- Klik Get started.
- Di kolom Additional providers, klik Google > Enable.
- Di kotak teks Public-facing name for project, masukkan nama yang mudah diingat, seperti
My Next.js app
. - Dari drop-down Support email for project, pilih alamat email Anda.
- Klik Save.
Menyiapkan Cloud Firestore
- Di panel kiri Firebase console, luaskan Build, lalu pilih Firestore database.
- Klik Buat database.
- Biarkan Database ID ditetapkan ke
(default)
. - Pilih lokasi untuk database Anda, lalu klik Berikutnya.
Untuk aplikasi yang sebenarnya, Anda ingin memilih lokasi yang dekat dengan pengguna. - Klik Mulai dalam mode pengujian. Baca pernyataan penyangkalan tentang aturan keamanan.
Di bagian akhir codelab ini, Anda akan menambahkan Aturan Keamanan untuk mengamankan data. Jangan mendistribusikan atau mengekspos aplikasi ke publik tanpa menambahkan Aturan Keamanan untuk database Anda. - Klik Buat.
Menyiapkan Cloud Storage for Firebase
- Di panel kiri Firebase console, luaskan Build, lalu pilih Storage.
- Klik Mulai.
- Pilih lokasi untuk bucket Storage default Anda.
Bucket dalamUS-WEST1
,US-CENTRAL1
, danUS-EAST1
dapat memanfaatkan tingkat "Selalu Gratis" untuk Google Cloud Storage. Bucket di semua lokasi lainnya mengikuti harga dan penggunaan Google Cloud Storage. - Klik Mulai dalam mode pengujian. Baca pernyataan penyangkalan tentang aturan keamanan.
Di bagian akhir codelab ini, Anda akan menambahkan aturan keamanan untuk mengamankan data. Jangan mendistribusikan atau mengekspos aplikasi ke publik tanpa menambahkan Aturan Keamanan untuk bucket Storage Anda. - Klik Buat.
4. Meninjau codebase awal
Di bagian ini, Anda akan meninjau beberapa area codebase awal aplikasi yang akan ditambahi fungsi dalam codelab ini.
Struktur folder dan file
Tabel berikut berisi ringkasan struktur folder dan file aplikasi:
Folder dan file | Deskripsi |
| Komponen React untuk filter, header, detail restoran, dan ulasan |
| Fungsi utilitas yang tidak harus terikat dengan React atau Next.js |
| Kode khusus Firebase dan konfigurasi Firebase |
| Aset statis di aplikasi web, seperti ikon |
| Memilih rute dengan Router Aplikasi Next.js |
| Pengendali rute API |
| Dependensi project dengan npm |
| Konfigurasi khusus Next.js (tindakan server diaktifkan) |
| Konfigurasi layanan bahasa JavaScript |
Komponen server dan klien
Aplikasi ini adalah aplikasi web Next.js yang menggunakan Router Aplikasi. Rendering server digunakan di seluruh aplikasi. Misalnya, file src/app/page.js
adalah komponen server yang bertanggung jawab atas halaman utama. File src/components/RestaurantListings.jsx
adalah komponen klien yang ditunjukkan oleh perintah "use client"
di awal file.
Pernyataan impor
Anda mungkin melihat pernyataan impor seperti berikut:
import RatingPicker from "@/src/components/RatingPicker.jsx";
Aplikasi menggunakan simbol @
untuk menghindari jalur impor relatif yang kaku dan dimungkinkan oleh alias jalur.
API khusus Firebase
Semua kode Firebase API digabungkan dalam direktori src/lib/firebase
. Setiap komponen React kemudian mengimpor fungsi yang digabungkan dari direktori src/lib/firebase
, bukan mengimpor fungsi Firebase secara langsung.
Data tiruan
Data restoran dan ulasan tiruan terdapat dalam file src/lib/randomData.js
. Data dari file tersebut disusun dalam kode di file src/lib/fakeRestaurants.js
.
5. Membuat backend App Hosting
Di bagian ini, Anda akan menyiapkan backend App Hosting untuk melihat cabang di repositori git Anda.
Di akhir bagian ini, Anda akan memiliki backend App Hosting yang terhubung ke repositori di GitHub yang akan otomatis mem-build ulang dan meluncurkan versi baru aplikasi setiap kali Anda mendorong commit baru ke cabang main
.
Men-deploy Aturan Keamanan
Kode ini sudah memiliki kumpulan aturan keamanan untuk Firestore dan Cloud Storage for Firebase. Setelah Anda men-deploy Aturan Keamanan, data dalam database dan bucket akan lebih terlindungi dari penyalahgunaan.
- Di terminal, konfigurasikan CLI untuk menggunakan project Firebase yang Anda buat sebelumnya:
Saat diminta untuk memasukkan alias, masukkanfirebase use --add
friendlyeats-codelab
. - Untuk men-deploy Aturan Keamanan ini, jalankan perintah ini di terminal Anda:
firebase deploy --only firestore:rules,storage
- Jika ditanya:
"Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?"
, tekanEnter
untuk memilih Yes.
Menambahkan konfigurasi Firebase ke kode aplikasi web
- Di Firebase console, buka Project settings.
- Di panel Penyiapan dan konfigurasi SDK, klik "Tambahkan aplikasi", lalu klik ikon tanda kurung kode
untuk mendaftarkan aplikasi web baru.
- Di akhir alur pembuatan aplikasi web, salin variabel
firebaseConfig
, lalu salin properti dan nilainya. - Buka file
apphosting.yaml
di editor kode Anda, dan isi nilai variabel lingkungan dengan nilai konfigurasi dari Firebase console. - Dalam file, ganti properti yang ada dengan properti yang Anda salin.
- Simpan file.
Membuat backend
- Buka halaman App Hosting di Firebase console:
- Klik "Mulai" untuk memulai alur pembuatan backend. Konfigurasi backend Anda sebagai berikut:
- Ikuti perintah di langkah pertama untuk menghubungkan repositori GitHub yang Anda buat sebelumnya.
- Tetapkan setelan penerapan:
- Pertahankan direktori utama sebagai
/
- Menetapkan cabang aktif ke
main
- Aktifkan peluncuran otomatis
- Pertahankan direktori utama sebagai
- Beri nama backend Anda
friendlyeats-codelab
. - Pada "Create or associate a Firebase web app", pilih aplikasi web yang telah Anda konfigurasi sebelumnya dari drop-down "Select an existing Firebase web app".
- Klik "Selesaikan dan deploy". Setelah beberapa saat, Anda akan diarahkan ke halaman baru tempat Anda dapat melihat status backend App Hosting yang baru.
- Setelah peluncuran selesai, klik domain gratis Anda di bagian "domains". Mungkin perlu waktu beberapa menit untuk mulai berfungsi karena penyebaran DNS.
Anda telah men-deploy aplikasi web awal. Setiap kali mengirim commit baru ke cabang main
dari repositori GitHub, Anda akan melihat build dan peluncuran baru dimulai di Firebase console, dan situs Anda akan otomatis diupdate setelah peluncuran selesai.
6. Menambahkan autentikasi ke aplikasi web
Di bagian ini, Anda akan menambahkan autentikasi ke aplikasi web sehingga Anda dapat login ke aplikasi tersebut.
Mengimplementasikan fungsi login dan logout
- Di file
src/lib/firebase/auth.js
, ganti fungsionAuthStateChanged
,signInWithGoogle
, dansignOut
dengan kode berikut:
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);
}
}
Kode ini menggunakan Firebase API berikut:
Firebase API | Deskripsi |
Membuat instance penyedia autentikasi Google. | |
Memulai alur autentikasi berbasis dialog. | |
Memproses logout pengguna. |
Dalam file src/components/Header.jsx
, kode sudah memanggil fungsi signInWithGoogle
dan signOut
.
- Buat commit dengan pesan commit "Menambahkan Autentikasi Google" dan kirim ke repositori GitHub Anda. 1. Buka halaman App Hosting di Firebase console dan tunggu peluncuran baru Anda selesai.
- Di aplikasi web, muat ulang halaman dan klik Sign in with Google. Aplikasi web tidak diupdate, sehingga tidak jelas apakah login berhasil atau tidak.
Mengirim status autentikasi ke server
Untuk meneruskan status autentikasi ke server, kita akan menggunakan pekerja layanan. Ganti fungsi fetchWithFirebaseHeaders
dan getAuthIdToken
dengan kode berikut:
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);
}
Membaca status autentikasi di server
Kita akan menggunakan FirebaseServerApp untuk mencerminkan status autentikasi klien di server.
Buka src/lib/firebase/serverApp.js
, dan ganti fungsi 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 };
}
Berlangganan perubahan autentikasi
Untuk berlangganan perubahan autentikasi, ikuti langkah-langkah berikut:
- Buka file
src/components/Header.jsx
. - Ganti fungsi
useUserSession
dengan kode berikut:
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;
}
Kode ini menggunakan hook status React untuk mengupdate pengguna saat fungsi onAuthStateChanged
menentukan bahwa ada perubahan pada status autentikasi.
Memverifikasi perubahan
Tata letak root di file src/app/layout.js
merender header dan meneruskan pengguna, jika tersedia, sebagai properti.
<Header initialUser={currentUser?.toJSON()} />
Ini berarti komponen <Header>
akan merender data pengguna, jika tersedia, selama waktu proses server. Jika ada update autentikasi selama siklus proses halaman setelah pemuatan halaman awal, pengendali onAuthStateChanged
akan menanganinya.
Sekarang saatnya meluncurkan build baru dan memverifikasi build yang Anda buat.
- Buat commit dengan pesan commit "Show signin state" dan kirim ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu peluncuran baru Anda selesai.
- Verifikasi perilaku autentikasi baru:
- Di browser, muat ulang aplikasi web. Nama tampilan Anda akan muncul di header.
- Logout dan login lagi. Halaman diupdate secara real time tanpa memuat ulang halaman. Anda dapat mengulangi langkah ini dengan pengguna lain.
- Opsional: Klik kanan aplikasi web, pilih View page source, lalu telusuri nama tampilan. Nama tampilan akan muncul di sumber HTML mentah yang ditampilkan dari server.
7. Melihat informasi restoran
Aplikasi web menyertakan data tiruan untuk restoran dan ulasan.
Menambahkan satu atau beberapa restoran
Untuk memasukkan data restoran tiruan ke database Cloud Firestore lokal Anda, ikuti langkah-langkah berikut:
- Di aplikasi web, pilih > Add sample restaurants.
- Di Firebase console di halaman Firestore Database, pilih restaurants. Anda akan melihat dokumen tingkat teratas dalam koleksi restoran, yang masing-masing mewakili restoran.
- Klik beberapa dokumen untuk menjelajahi properti dokumen restoran.
Menampilkan daftar restoran
Database Cloud Firestore Anda sekarang memiliki restoran yang dapat ditampilkan oleh aplikasi web Next.js.
Untuk menentukan kode pengambilan data, ikuti langkah-langkah berikut:
- Dalam file
src/app/page.js
, temukan komponen server<Home />
, dan tinjau panggilan ke fungsigetRestaurants
, yang mengambil daftar restoran pada waktu proses server. Anda akan menerapkan fungsigetRestaurants
dalam langkah-langkah berikut. - Di file
src/lib/firebase/firestore.js
, ganti fungsiapplyQueryFilters
dangetRestaurants
dengan kode berikut:
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(),
};
});
}
- Buat commit dengan pesan commit "Baca daftar restoran dari Firestore" dan kirim ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu peluncuran baru Anda selesai.
- Di aplikasi web, muat ulang halaman. Gambar restoran muncul sebagai kotak di halaman.
Memastikan listingan restoran dimuat pada waktu proses server
Dengan menggunakan framework Next.js, mungkin akan sulit untuk mengetahui kapan data dimuat pada waktu proses server atau waktu proses sisi klien.
Untuk memverifikasi bahwa listingan restoran dimuat pada waktu proses server, ikuti langkah-langkah berikut:
- Di aplikasi web, buka DevTools dan nonaktifkan JavaScript.
- Muat ulang aplikasi web. Listingan restoran masih dimuat. Informasi restoran ditampilkan di respons server. Jika JavaScript diaktifkan, informasi restoran dihidrasi melalui kode JavaScript sisi klien.
- Di DevTools, aktifkan kembali JavaScript.
Memproses update restoran dengan pemroses snapshot Cloud Firestore
Di bagian sebelumnya, Anda telah melihat cara kumpulan restoran awal dimuat dari file src/app/page.js
. File src/app/page.js
adalah komponen server dan dirender di server, termasuk kode pengambilan data Firebase.
File src/components/RestaurantListings.jsx
adalah komponen klien dan dapat dikonfigurasi untuk menghidrasi markup yang dirender server.
Untuk mengonfigurasi file src/components/RestaurantListings.jsx
guna menghidrasi markup yang dirender server, ikuti langkah-langkah berikut:
- Dalam file
src/components/RestaurantListings.jsx
, amati kode berikut, yang sudah ditulis untuk Anda:
useEffect(() => {
const unsubscribe = getRestaurantsSnapshot(data => {
setRestaurants(data);
}, filters);
return () => {
unsubscribe();
};
}, [filters]);
Kode ini memanggil fungsi getRestaurantsSnapshot()
, yang mirip dengan fungsi getRestaurants()
yang Anda implementasikan di langkah sebelumnya. Namun, fungsi snapshot ini menyediakan mekanisme callback sehingga callback dipanggil setiap kali perubahan dilakukan pada koleksi restoran.
- Di file
src/lib/firebase/firestore.js
, ganti fungsigetRestaurantsSnapshot()
dengan kode berikut:
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;
}
Perubahan yang dilakukan melalui halaman Database Firestore kini tercermin di aplikasi web secara real time.
- Buat commit dengan pesan commit "Dengarkan update restoran realtime" dan kirim ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu peluncuran baru Anda selesai.
- Di aplikasi web, pilih > Add sample restaurants. Jika fungsi snapshot Anda diterapkan dengan benar, restoran akan muncul secara real time tanpa memuat ulang halaman.
8. Menyimpan ulasan yang dikirimkan pengguna dari aplikasi web
- Di file
src/lib/firebase/firestore.js
, ganti fungsiupdateWithRating()
dengan kode berikut:
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()),
});
};
Kode ini menyisipkan dokumen Firestore baru yang mewakili ulasan baru. Kode ini juga mengupdate dokumen Firestore yang ada yang mewakili restoran dengan angka yang diperbarui untuk jumlah rating dan rata-rata rating yang dihitung.
- Ganti fungsi
addReviewToRestaurant()
dengan kode berikut:
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;
}
}
Mengimplementasikan Tindakan Server Next.js
Tindakan Server Next.js menyediakan API yang mudah digunakan untuk mengakses data formulir, seperti data.get("text")
untuk mendapatkan nilai teks dari payload pengiriman formulir.
Untuk menggunakan Tindakan Server Next.js guna memproses pengiriman formulir peninjauan, ikuti langkah-langkah berikut:
- Dalam file
src/components/ReviewDialog.jsx
, temukan atributaction
di elemen<form>
.
<form action={handleReviewFormSubmission}>
Nilai atribut action
mengacu pada fungsi yang Anda implementasikan di langkah berikutnya.
- Di file
src/app/actions.js
, ganti fungsihandleReviewFormSubmission()
dengan kode berikut:
// 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"),
});
}
Menambahkan ulasan restoran
Anda telah menerapkan dukungan untuk pengiriman ulasan, jadi sekarang Anda dapat memverifikasi bahwa ulasan Anda disisipkan ke Cloud Firestore dengan benar.
Untuk menambahkan ulasan dan memverifikasi bahwa ulasan tersebut disisipkan ke Cloud Firestore, ikuti langkah-langkah berikut:
- Buat commit dengan pesan commit "Izinkan pengguna mengirimkan ulasan restoran" dan kirimkan ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu hingga peluncuran baru selesai.
- Muat ulang aplikasi web, lalu pilih restoran dari halaman beranda.
- Di halaman restoran, klik .
- Pilih rating bintang.
- Tulis ulasan.
- Klik Submit. Ulasan Anda akan muncul di bagian atas daftar ulasan.
- Di Cloud Firestore, telusuri panel Add document untuk dokumen restoran yang telah Anda ulas dan pilih dokumen tersebut.
- Di panel Start collection, pilih ratings.
- Di panel Add document, temukan dokumen untuk peninjauan Anda guna memverifikasi bahwa dokumen tersebut disisipkan seperti yang diharapkan.
9. Menyimpan file yang diupload pengguna dari aplikasi web
Di bagian ini, Anda menambahkan fungsi sehingga Anda dapat mengganti gambar yang terkait dengan restoran saat Anda login. Anda mengupload gambar ke Firebase Storage, dan mengupdate URL gambar di dokumen Cloud Firestore yang mewakili restoran.
Untuk menyimpan file yang diupload pengguna dari aplikasi web, ikuti langkah-langkah berikut:
- Di file
src/components/Restaurant.jsx
, amati kode yang berjalan saat pengguna mengupload file:
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 });
}
Perubahan tidak diperlukan, tetapi Anda menerapkan perilaku fungsi updateRestaurantImage()
dalam langkah-langkah berikut.
- Di file
src/lib/firebase/storage.js
, ganti fungsiupdateRestaurantImage()
danuploadImage()
dengan kode berikut:
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);
}
Fungsi updateRestaurantImageReference()
sudah diimplementasikan untuk Anda. Fungsi ini mengupdate dokumen restoran yang ada di Cloud Firestore dengan URL gambar yang diupdate.
Memverifikasi fungsi upload gambar
Untuk memastikan bahwa gambar diupload seperti yang diharapkan, ikuti langkah-langkah berikut:
- Buat commit dengan pesan commit "Izinkan pengguna mengubah setiap foto restoran" dan kirimkan ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu hingga peluncuran baru selesai.
- Di aplikasi web, pastikan Anda login dan pilih restoran.
- Klik lalu upload gambar dari sistem file Anda. Gambar Anda meninggalkan lingkungan lokal dan diupload ke Cloud Storage. Gambar akan langsung muncul setelah Anda menguploadnya.
- Buka Cloud Storage for Firebase.
- Buka folder yang mewakili restoran. Gambar yang Anda upload ada di folder.
10. Meringkas ulasan restoran dengan AI generatif
Di bagian ini, Anda akan menambahkan fitur ringkasan ulasan sehingga pengguna dapat dengan cepat memahami pendapat semua orang tentang suatu restoran tanpa harus membaca setiap ulasan.
Menyimpan kunci Gemini API di Cloud Secret Manager
- Untuk menggunakan Gemini API, Anda memerlukan kunci API. Buat kunci di Google AI Studio.
- App Hosting terintegrasi dengan Cloud Secret Manager untuk memungkinkan Anda menyimpan nilai sensitif seperti kunci API dengan aman:
- Di terminal, jalankan perintah untuk membuat secret baru:
firebase apphosting:secrets:set gemini-api-key
- Saat diminta memasukkan nilai rahasia, salin dan tempel kunci Gemini API Anda dari Google AI Studio.
- Saat ditanya apakah secret baru harus ditambahkan ke
apphosting.yaml
, masukkanY
untuk menyetujui.
Kunci Gemini API Anda kini disimpan dengan aman di Cloud Secret Manager, dan dapat diakses oleh backend App Hosting Anda.
Menerapkan komponen ringkasan ulasan
- Di
src/components/Reviews/ReviewSummary.jsx
, ganti fungsiGeminiSummary
dengan kode berikut: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>; } }
- Buat commit dengan pesan commit "Use AI to summarize reviews" dan kirim ke repositori GitHub Anda.
- Buka halaman App Hosting di Firebase console dan tunggu hingga peluncuran baru selesai.
- Buka halaman untuk restoran. Di bagian atas, Anda akan melihat ringkasan satu kalimat dari semua ulasan di halaman.
- Tambahkan ulasan baru dan muat ulang halaman. Anda akan melihat perubahan ringkasan.
11. Kesimpulan
Selamat! Anda telah mempelajari cara menggunakan Firebase untuk menambahkan fitur dan fungsi ke aplikasi Next.js. Secara khusus, Anda telah menggunakan hal berikut:
- Firebase App Hosting untuk mem-build dan men-deploy kode Next.js secara otomatis setiap kali Anda melakukan push ke cabang yang dikonfigurasi.
- Firebase Authentication untuk mengaktifkan fungsi login dan logout.
- Cloud Firestore untuk data restoran dan data ulasan restoran.
- Cloud Storage for Firebase untuk gambar restoran.