Firebase'i Next.js uygulamasıyla entegre etme

1. Başlamadan önce

Bu codelab'de, Firebase'i restoran yorumları web sitesi olan Friendly Eats adlı bir Next.js web uygulamasına nasıl entegre edeceğinizi öğreneceksiniz.

Friendly Eats web uygulaması

Tamamlanan web uygulaması, Firebase'in Next.js uygulamaları geliştirmenize nasıl yardımcı olabileceğini gösteren faydalı özellikler sunar. Bu özellikler şunlardır:

  • Otomatik derleme ve dağıtım: Bu kod deneme çalışması, yapılandırılmış bir dallara her push yaptığınızda Next.js kodunuzu otomatik olarak derlemek ve dağıtmak için Firebase App Hosting'i kullanır.
  • Oturum açma ve oturum kapatma: Tamamlanan web uygulaması, Google ile oturum açmanıza ve oturumu kapatmanıza olanak tanır. Kullanıcı girişi ve devamlılık tamamen Firebase Authentication üzerinden yönetilir.
  • Resimler: Tamamlanmış web uygulaması, oturum açmış kullanıcıların restoran resimleri yüklemesine olanak tanır. Resim öğeleri Firebase için Cloud Storage'da depolanır. Firebase JavaScript SDK'sı, yüklenen resimlerin herkese açık URL'sini sağlar. Bu herkese açık URL daha sonra Cloud Firestore'daki ilgili restoran belgesinde depolanır.
  • Yorumlar: Tamamlanmış web uygulaması, oturum açmış kullanıcıların restoranlar hakkında yıldız puanı ve metin tabanlı mesajdan oluşan yorumlar yayınlamasına olanak tanır. İnceleme bilgileri Cloud Firestore'da depolanır.
  • Filtreler: Tamamlanmış web uygulaması, oturum açmış kullanıcıların restoran listesini kategoriye, konuma ve fiyata göre filtrelemesine olanak tanır. Kullanılan sıralama yöntemini de özelleştirebilirsiniz. Verilere Cloud Firestore'dan erişilir ve Firestore sorguları, kullanılan filtrelere göre uygulanır.

Ön koşullar

  • GitHub hesabı
  • Next.js ve JavaScript hakkında bilgi

Neler öğreneceksiniz?

  • Firebase'i Next.js uygulama yönlendiricisi ve sunucu tarafı oluşturma ile kullanma.
  • Resimleri Firebase için Cloud Storage'da kalıcı hale getirme.
  • Cloud Firestore veritabanında veri okuma ve yazma.
  • Firebase JavaScript SDK'sı ile Google ile oturum açma özelliğini kullanma.

Gerekenler

  • Git
  • Node.js'in son kararlı sürümü
  • Google Chrome gibi tercih ettiğiniz bir tarayıcı
  • Kod düzenleyici ve terminal içeren bir geliştirme ortamı
  • Firebase projenizi oluşturmak ve yönetmek için bir Google Hesabı
  • Firebase projenizi Blaze fiyatlandırma planına yükseltme olanağı

2. Geliştirme ortamınızı ve GitHub deponuzu ayarlama

Bu codelab, uygulamanın başlangıç kod tabanını sağlar ve Firebase CLI'yi kullanır.

GitHub deposu oluşturma

Codelab kaynağını https://github.com/firebase/friendlyeats-web adresinde bulabilirsiniz. Depo, birden fazla platform için örnek projeler içerir. Ancak bu kod laboratuvarında yalnızca nextjs-start dizini kullanılır. Aşağıdaki dizinleri göz önünde bulundurun:

* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.

nextjs-start klasörünü kendi deponuza kopyalayın:

  1. Terminal kullanarak bilgisayarınızda yeni bir klasör oluşturun ve yeni dizine geçin:
    mkdir codelab-friendlyeats-web
    
    cd codelab-friendlyeats-web
    
  2. Yalnızca nextjs-start klasörünü almak için giget npm paketini kullanın:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
    
  3. Git ile değişiklikleri yerel olarak izleme:
    git init
    
    git add .
    
    git commit -m "codelab starting point"
    
    git branch -M main
    
  4. Yeni bir GitHub deposu oluşturun: https://github.com/new. İstediğiniz adı verin.
  5. GitHub'ın sizin için oluşturduğu yeni URL'yi kopyalayın. Aşağıdakilerden birine benzer:
    • https://github.com/<USER_NAME>/<REPOSITORY_NAME>.git veya
    • git@github.com:<USER_NAME>/<REPOSITORY_NAME>.git
  6. Aşağıdaki komutu çalıştırarak yerel değişiklikleri yeni GitHub deponuza aktarın. <REPOSITORY_URL> yer tutucusunu gerçek depolama alanı URL'nizle değiştirin.
    git remote add origin <REPOSITORY_URL>
    
    git push -u origin main
    
  7. Artık GitHub deponuzda başlangıç kodunu görebilirsiniz.

Firebase CLI'yi yükleme veya güncelleme

Firebase CLI'nin yüklü olduğunu ve v14.1.0 veya sonraki bir sürüm olduğunu doğrulamak için aşağıdaki komutu çalıştırın:

firebase --version

Daha düşük bir sürüm görüyorsanız veya Firebase CLI yüklü değilse yükleme komutunu çalıştırın:

npm install -g firebase-tools@latest

İzin hataları nedeniyle Firebase CLI'yi yükleyemiyorsanız npm belgelerine bakın veya başka bir yükleme seçeneği kullanın.

Firebase'e giriş yapma

  1. Firebase CLI'ye giriş yapmak için aşağıdaki komutu çalıştırın:
    firebase login
    
  2. Firebase'in veri toplamasını isteyip istemediğinize bağlı olarak Y veya N değerini girin.
  3. Tarayıcınızda Google Hesabınızı seçin ve ardından İzin ver'i tıklayın.

3. Firebase projenizi ayarlama

Bu bölümde, bir Firebase projesi oluşturacak ve bu projeyle bir Firebase web uygulaması ilişkilendireceksiniz. Ayrıca, örnek web uygulamasının kullandığı Firebase hizmetlerini de ayarlayacaksınız.

Firebase projesi oluşturma

  1. Firebase konsolunda Proje ekle'yi tıklayın.
  2. Proje adınızı girin metin kutusuna FriendlyEats Codelab (veya istediğiniz bir proje adı) girin ve Devam'ı tıklayın.
  3. Bu kod laboratuvarının çalışması için Google Analytics'e ihtiyacınız yoktur. Bu nedenle, Bu proje için Google Analytics'i etkinleştir seçeneğini devre dışı bırakın.
  4. Proje oluştur'u tıklayın.
  5. Projenizin temel hazırlığını yapılmasını bekleyin ve ardından Devam'ı tıklayın.
  6. Firebase projenizde Proje Ayarları'na gidin. Daha sonra ihtiyacınız olacağından proje kimliğinizi not edin. Bu benzersiz tanımlayıcı, projenizin kimliğini belirler (ör. Firebase CLI'de).

Firebase fiyatlandırma planınızı yükseltme

Firebase için Firebase Uygulama Barındırma ve Cloud Depolama'yı kullanmak istiyorsanız Firebase projenizin kullandıkça öde (Blaze) fiyatlandırma planında olması gerekir. Yani projeniz bir Cloud Faturalandırma hesabına bağlı olmalıdır.

  • Cloud Billing hesabı için kredi kartı gibi bir ödeme yöntemi gerekir.
  • Firebase ve Google Cloud'da yeniyseniz 300 ABD doları kredi ve ücretsiz deneme Cloud faturalandırma hesabı almaya uygun olup olmadığınızı kontrol edin.
  • Bu kod laboratuvarını bir etkinlik kapsamında yapıyorsanız düzenleyen kişiye Cloud kredisi olup olmadığını sorun.

Projenizi Blaze planına yükseltmek için aşağıdaki adımları uygulayın:

  1. Firebase konsolunda planınızı yükseltmeyi seçin.
  2. Blaze planını seçin. Projenize bir Cloud Faturalandırma hesabı bağlamak için ekrandaki talimatları uygulayın.
    Bu yükseltme kapsamında bir Cloud Faturalandırma hesabı oluşturmanız gerekiyorsa yükseltmeyi tamamlamak için Firebase Console'daki yükseltme akışına geri dönmeniz gerekebilir.

Firebase projenize web uygulaması ekleme

  1. Firebase projenizde Projeye genel bakış'a gidin ve ardından e41f2efdd9539c31.png Web'i tıklayın.

    Projenize kayıtlı uygulamalar varsa Web simgesini görmek için Uygulama ekle'yi tıklayın.
  2. Uygulama takma adı metin kutusuna My Next.js app gibi akılda kalıcı bir uygulama takma adı girin.
  3. Bu uygulama için Firebase Hosting'i de ayarlayın onay kutusunu işaretlemeden bırakın.
  4. Uygulamayı kaydet > Konsola devam et'i tıklayın.

Firebase konsolunda Firebase hizmetlerini ayarlama

Kimlik doğrulamayı ayarlama

  1. Firebase konsolunda Kimlik doğrulama'ya gidin.
  2. Başlayın'ı tıklayın.
  3. Ek sağlayıcılar sütununda Google > Etkinleştir'i tıklayın.
  4. Projenin herkese açık adı metin kutusuna My Next.js app gibi akılda kalıcı bir ad girin.
  5. Proje için destek e-postası açılır listesinden e-posta adresinizi seçin.
  6. Kaydet'i tıklayın.

Cloud Firestore'u ayarlama

  1. Firebase konsolunun sol panelinde Derleme'yi genişletin ve ardından Firestore Veritabanı'nı seçin.
  2. Create database'i (Veritabanı oluştur) tıklayın.
  3. Veritabanı Kimliği'ni (default) olarak bırakın.
  4. Veritabanı için bir konum seçin ve Sonraki'yi tıklayın.
    Gerçek bir uygulama için kullanıcılarınıza yakın bir konum seçmeniz gerekir.
  5. Test modunda başlat'ı tıklayın. Güvenlik kurallarıyla ilgili sorumluluk reddi beyanını okuyun.
    Bu kod laboratuvarının ilerleyen bölümlerinde, verilerinizin güvenliğini sağlamak için güvenlik kuralları ekleyeceksiniz. Veritabanınıza Güvenlik Kuralları eklemeden bir uygulamayı dağıtmayın veya herkese açık olarak göstermeyin.
  6. Oluştur'u tıklayın.

Cloud Storage for Firebase'ı ayarlama

  1. Firebase konsolunun sol panelinde Derleme'yi genişletin ve ardından Depolama'yı seçin.
  2. Başlayın'ı tıklayın.
  3. Varsayılan Storage paketiniz için bir konum seçin.
    US-WEST1, US-CENTRAL1 ve US-EAST1'deki paketler, Google Cloud Storage'ın "Daima Ücretsiz" katmanından yararlanabilir. Diğer tüm konumlardaki paketler için Google Cloud Storage fiyatlandırması ve kullanımı geçerlidir.
  4. Test modunda başlat'ı tıklayın. Güvenlik kurallarıyla ilgili sorumluluk reddi beyanını okuyun.
    Bu kod laboratuvarının ilerleyen bölümlerinde, verilerinizin güvenliğini sağlamak için güvenlik kuralları ekleyeceksiniz. Depolama alanı paketiniz için güvenlik kuralları eklemeden bir uygulamayı dağıtmayın veya herkese açık olarak göstermeyin.
  5. Oluştur'u tıklayın.

Güvenlik kurallarını dağıtma

Kodda zaten Firestore ve Cloud Storage for Firebase için güvenlik kuralı grupları vardır. Güvenlik kurallarını dağıttıktan sonra veritabanınızdaki ve paketinizdeki veriler kötüye kullanıma karşı daha iyi korunur.

  1. Terminalinizde, CLI'yi daha önce oluşturduğunuz Firebase projesini kullanacak şekilde yapılandırın:
    firebase use --add
    
    Takma ad istendiğinde friendlyeats-codelab yazın.
  2. Bu güvenlik kurallarını (ve daha sonra ihtiyaç duyulacak dizinleri) dağıtmak için terminalinizde şu komutu çalıştırın:
    firebase deploy --only firestore,storage
    
  3. Şu soruyu görürseniz: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" Evet'i seçmek için Enter tuşuna basın.

4. Başlangıç kod tabanını inceleme

Bu bölümde, uygulamanın başlangıç kod tabanının bu codelab'de işlev ekleyeceğiniz birkaç alanını inceleyeceksiniz.

Klasör ve dosya yapısı

Aşağıdaki tabloda, uygulamanın klasör ve dosya yapısına genel bir bakış sunulmaktadır:

Klasörler ve dosyalar

Açıklama

src/components

Filtreler, üstbilgiler, restoran ayrıntıları ve yorumlar için React bileşenleri

src/lib

React veya Next.js'ye bağlı olmayan yardımcı işlevler

src/lib/firebase

Firebase'e özgü kod ve Firebase yapılandırması

public

Web uygulamasındaki statik öğeler (ör. simgeler)

src/app

Next.js uygulama yönlendiricisiyle yönlendirme

package.json ve package-lock.json

npm ile proje bağımlılıkları

next.config.js

Next.js'ye özgü yapılandırma (sunucu işlemleri etkindir)

jsconfig.json

JavaScript dil hizmeti yapılandırması

Sunucu ve istemci bileşenleri

Uygulama, uygulama yönlendiricisini kullanan bir Next.js web uygulamasıdır. Sunucu oluşturma, uygulama genelinde kullanılır. Örneğin, src/app/page.js dosyası ana sayfadan sorumlu bir sunucu bileşenidir. src/components/RestaurantListings.jsx dosyası, dosyanın başındaki "use client" yönergesiyle belirtilen bir istemci bileşenidir.

Ekstreleri içe aktarma

Aşağıdaki gibi içe aktarma beyanları görebilirsiniz:

import RatingPicker from "@/src/components/RatingPicker.jsx";

Uygulama, hantal göreli içe aktarma yollarını önlemek için @ simgesini kullanır ve bu, yol takma adları sayesinde mümkün olur.

Firebase'e özgü API'ler

Tüm Firebase API kodu src/lib/firebase dizinine yerleştirilir. Ayrı React bileşenleri, Firebase işlevlerini doğrudan içe aktarmak yerine sarmalanmış işlevleri src/lib/firebase dizininden içe aktarır.

Sahte veriler

Sahte restoran ve yorum verileri src/lib/randomData.js dosyasında yer alır. Bu dosyadaki veriler, src/lib/fakeRestaurants.js dosyasındaki kodda birleştirilir.

5. Uygulama barındırma arka ucu oluşturma

Bu bölümde, git deponuzdaki bir dalı izlemek için Uygulama Barındırma arka ucu oluşturacaksınız.

Bu bölümün sonunda, GitHub'daki deponuza bağlı bir App Hosting arka ucuna sahip olacaksınız. Bu arka uç, main dalınıza yeni bir gönderim gönderdiğinizde uygulamanızı otomatik olarak yeniden derleyip yeni bir sürümünü kullanıma sunar.

Arka uç oluşturma

  1. Firebase konsolunda Uygulama Barındırma sayfasına gidin:

&quot;Başlayın&quot; düğmesi içeren uygulama barındırma konsolunun sıfır durumu

  1. Arka uç oluşturma akışını başlatmak için "Başlayın"ı tıklayın. Arka ucunuzu aşağıdaki gibi yapılandırın:
  2. Bölge seçin. Gerçek bir uygulama için kullanıcılarınıza en yakın bölgeyi seçersiniz.
  3. Daha önce oluşturduğunuz GitHub deposunu bağlamak için "GitHub deposu içe aktarma" adımındaki talimatları uygulayın.
  4. Dağıtım ayarlarını yapın:
    1. Kök dizini / olarak kalsın
    2. Canlı şubeyi main olarak ayarlayın
    3. Otomatik kullanıma sunma işlemlerini etkinleştirme
  5. Arka uçunuzu friendlyeats-codelab olarak adlandırın.
  6. "Firebase web uygulaması ilişkilendir" bölümünde "Yeni Firebase web uygulaması oluştur"u tıklayın.
  7. "Sonlandır ve dağıt"ı tıklayın. Bir süre sonra, yeni uygulama barındırma arka uç sunucunuzun durumunu görebileceğiniz yeni bir sayfaya yönlendirilirsiniz.
  8. Kullanıma sunma işleminiz tamamlandıktan sonra "Alanlar" bölümünde ücretsiz alanınızı tıklayın. DNS yayımı nedeniyle bu özelliğin çalışmaya başlaması birkaç dakika sürebilir.
  9. Hata oluştu. Sayfayı yüklediğinizde "Uygulama hatası: Sunucu tarafında bir istisna oluştu (daha fazla bilgi için sunucu günlüklerine bakın)" hata mesajını görürsünüz.
  10. Firebase konsolunda, uygulama barındırma arka uç sunucunuzun "Günlükler" sekmesini kontrol edin. "Hata: uygulanmadı" günlüğünü görürsünüz. Kimlik doğrulama eklediğimiz sonraki adımda bu sorunu düzeltiriz.

İlk web uygulamasını dağıttınız. GitHub deponuzun main dalına her yeni kaydetme işlemi aktardığınızda Firebase konsolunda yeni bir derleme ve dağıtım işleminin başladığını görürsünüz. Dağıtım tamamlandığında siteniz otomatik olarak güncellenir.

6. Web uygulamasına kimlik doğrulama ekleme

Bu bölümde, web uygulamasına giriş yapabilmeniz için kimlik doğrulaması eklersiniz.

Yetkilendirilen alan ekleyin

Firebase Authentication yalnızca izin verdiğiniz alanlardan gelen oturum açma isteklerini kabul eder. Burada, uygulama barındırma arka uç alanınızın alan adını projenizdeki onaylanmış alanlar listesine ekleriz.

  1. Uygulama Barındırma "Genel Bakış" sayfasından uygulama barındırma arka uç alanınızın adını kopyalayın.
  2. Kimlik doğrulama Ayarları sekmesine gidin ve Yetkili Alanlar'ı seçin.
  3. Alan ekle düğmesini tıklayın.
  4. Uygulama barındırma arka uç sunucunuzun alanını girin.
  5. Ekle'yi tıklayın.

Oturum açma ve oturumu kapatma işlevlerini uygulama

  1. src/lib/firebase/auth.js dosyasında onAuthStateChanged, onIdTokenChanged, signInWithGoogle ve signOut işlevlerini aşağıdaki kodla değiştirin:
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);
  }
}

Bu kod aşağıdaki Firebase API'lerini kullanır:

Firebase API

Açıklama

auth.onAuthStateChanged

Kullanıcının oturum açma durumundaki değişiklikler için bir gözlemci ekler.

auth.onIdTokenChanged

Kullanıcının kimlik jetonunda yapılan değişiklikler için bir gözlemci ekler.

GoogleAuthProvider

Google kimlik doğrulama sağlayıcı örneği oluşturur.

signInWithPopup

İletişime dayalı bir kimlik doğrulama akışı başlatır.

auth.signOut

Kullanıcının oturumu kapatılır.

src/components/Header.jsx dosyasında kod zaten signInWithGoogle ve signOut işlevlerini çağırıyor.

Kimlik doğrulama durumunu sunucuya gönderme

Kimlik doğrulama durumunu sunucuya iletmek için çerezleri kullanırız. İstemcide kimlik doğrulama durumu her değiştiğinde __session çerezini güncelleriz.

src/components/Header.jsx içinde useUserSession işlevini aşağıdaki kodla değiştirin:

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;
}

Sunucudaki kimlik doğrulama durumunu okuma

İstemcinin kimlik doğrulama durumunu sunucuya yansıtmak için FirebaseServerApp sınıfını kullanacağız.

src/lib/firebase/serverApp.js dosyasını açıp getAuthenticatedAppForUser işlevini değiştirin:

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 };
}

Değişiklikleri doğrulama

src/app/layout.js dosyasındaki kök düzen, başlığı oluşturur ve varsa kullanıcıyı öğe olarak iletir.

<Header initialUser={currentUser?.toJSON()} />

Bu, <Header> bileşeninin, sunucu çalışma zamanında (varsa) kullanıcı verilerini oluşturacağı anlamına gelir. İlk sayfa yükleme işleminden sonra sayfa yaşam döngüsü sırasında herhangi bir kimlik doğrulama güncellemesi olursa bunları onAuthStateChanged işleyicisi yönetir.

Artık yeni bir derleme yayınlamanın ve oluşturduğunuzu doğrulamanın zamanı geldi.

  1. "Kimlik doğrulama ekle" commit mesajını içeren bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  3. Yeni kimlik doğrulama davranışını doğrulayın:
    1. Tarayıcınızda web uygulamasını yenileyin. Görünen adınız üstbilgide görünür.
    2. Oturumu kapatıp tekrar açın. Bu adımı farklı kullanıcılarla tekrarlayabilirsiniz.
    3. İsteğe bağlı: Web uygulamasını sağ tıklayın, Sayfa kaynağını görüntüle'yi seçin ve görünen adı arayın. Bu değer, sunucudan döndürülen ham HTML kaynağında görünür.

7. Restoran bilgilerini görüntüleme

Web uygulaması, restoranlar ve yorumlar için örnek veriler içerir.

Bir veya daha fazla restoran ekleme

Yerel Cloud Firestore veritabanınıza örnek restoran verileri eklemek için aşağıdaki adımları uygulayın:

  1. Henüz yapmadıysanız web uygulamasında oturum açın. Ardından 2cf67d488d8e6332.png > Örnek restoran ekle'yi seçin.
  2. Firebase konsolundaki Firestore Veritabanı sayfasında restaurants'ı seçin. Restoran koleksiyonunda, her biri bir restoranı temsil eden üst düzey dokümanları görürsünüz.
  3. Bir restoran belgesinin özelliklerini keşfetmek için birkaç belgeyi tıklayın.

Restoran listesini görüntüleme

Cloud Firestore veritabanınızda artık Next.js web uygulamasının görüntüleyebileceği restoranlar var.

Veri getirme kodunu tanımlamak için aşağıdaki adımları uygulayın:

  1. src/app/page.js dosyasında <Home /> sunucu bileşenini bulun ve sunucu çalışma zamanında restoranların listesini alan getRestaurants işlevinin çağrısını inceleyin. getRestaurants işlevini aşağıdaki adımlarda uygularsınız.
  2. src/lib/firebase/firestore.js dosyasında applyQueryFilters ve getRestaurants işlevlerini aşağıdaki kodla değiştirin:
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(),
    };
  });
}
  1. "Firestore'dan restoran listesini oku" commit mesajını içeren bir commit oluşturun ve GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  3. Web uygulamasında sayfayı yenileyin. Restoran resimleri sayfada karolar olarak görünür.

Restoran listelemelerinin sunucu çalışma zamanında yüklendiğini doğrulama

Next.js çerçevesi kullanıldığında verilerin sunucu çalışma zamanında mı yoksa istemci tarafında çalışma zamanında mı yüklendiği açık olmayabilir.

Restoran listelemelerinin sunucu çalışma zamanında yüklendiğini doğrulamak için aşağıdaki adımları uygulayın:

  1. Web uygulamasında Geliştirici Araçları'nı açın ve JavaScript'i devre dışı bırakın.

DevTools&#39;da JavaScript&#39;i devre dışı bırakma

  1. Web uygulamasını yenileyin. Restoran girişleri yine yüklenir. Restoran bilgileri sunucu yanıtında döndürülür. JavaScript etkinleştirildiğinde restoran bilgileri, istemci tarafı JavaScript kodu aracılığıyla etkinleştirilir.
  2. Geliştirici Araçları'nda JavaScript'i yeniden etkinleştirin.

Cloud Firestore anlık görüntü dinleyicileriyle restoran güncellemelerini dinleme

Önceki bölümde, ilk restoran grubunun src/app/page.js dosyasından nasıl yüklendiğini gördünüz. src/app/page.js dosyası bir sunucu bileşenidir ve Firebase veri getirme kodu da dahil olmak üzere sunucuda oluşturulur.

src/components/RestaurantListings.jsx dosyası bir istemci bileşenidir ve sunucu tarafından oluşturulan işaretlemeyi besleyecek şekilde yapılandırılabilir.

src/components/RestaurantListings.jsx dosyasını, sunucu tarafından oluşturulan işaretlemeyi besleyecek şekilde yapılandırmak için aşağıdaki adımları uygulayın:

  1. src/components/RestaurantListings.jsx dosyasında, sizin için önceden yazılmış aşağıdaki kodu inceleyin:
useEffect(() => {
    return getRestaurantsSnapshot((data) => {
      setRestaurants(data);
    }, filters);
  }, [filters]);

Bu kod, önceki bir adımda uyguladığınız getRestaurants() işlevine benzer bir getRestaurantsSnapshot() işlevi çağırır. Ancak bu anlık görüntü işlevi, restoranın koleksiyonunda her değişiklik yapıldığında geri çağırma işlevinin çağrılması için bir geri çağırma mekanizması sağlar.

  1. src/lib/firebase/firestore.js dosyasında getRestaurantsSnapshot() işlevini aşağıdaki kodla değiştirin:
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);
  });
}

Firestore Veritabanı sayfası üzerinden yapılan değişiklikler artık web uygulamasına anında yansıtılıyor.

  1. "Anlık restoran güncellemelerini dinleyin" mesajını içeren bir kaydetme işlemi oluşturun ve bu kaydetme işlemini GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  3. Web uygulamasında 27ca5d1e8ed8adfe.png > Örnek restoran ekle'yi seçin. Anlık görüntü işleviniz doğru şekilde uygulandıysa restoranlar sayfa yenilenmeden anlık olarak gösterilir.

8. Kullanıcı tarafından gönderilen yorumları web uygulamasından kaydetme

  1. src/lib/firebase/firestore.js dosyasında updateWithRating() işlevini aşağıdaki kodla değiştirin:
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()),
  });
};

Bu kod, yeni incelemeyi temsil eden yeni bir Firestore dokümanı ekler. Kod, restoranı temsil eden mevcut Firestore belgesini de puan sayısı ve ortalama hesaplanan puanla ilgili güncellenmiş rakamlarla günceller.

  1. addReviewToRestaurant() işlevini aşağıdaki kodla değiştirin:
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;
	}
}

Next.js sunucu işlemi uygulama

Next.js sunucu işlemi, form verilerine erişmek için uygun bir API sağlar. Örneğin, form gönderme yükünden metin değerini almak için data.get("text") kullanılır.

İnceleme formu gönderimini işlemek için Next.js sunucu işlemi kullanmak üzere aşağıdaki adımları uygulayın:

  1. src/components/ReviewDialog.jsx dosyasında, <form> öğesinde action özelliğini bulun.
<form action={handleReviewFormSubmission}>

action özellik değeri, bir sonraki adımda uygulayacağınız bir işlevi ifade eder.

  1. src/app/actions.js dosyasında handleReviewFormSubmission() işlevini aşağıdaki kodla değiştirin:
// 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"),
        });
}

Restoran yorumları ekleme

Yorum gönderimleri için destek uyguladığınızdan artık yorumlarınızın Cloud Firestore'a doğru şekilde eklendiğini doğrulayabilirsiniz.

Yorum eklemek ve yorumun Cloud Firestore'a eklendiğini doğrulamak için aşağıdaki adımları uygulayın:

  1. "Kullanıcıların restoran yorumları göndermesine izin ver" commit mesajını içeren bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  3. Web uygulamasını yenileyin ve ana sayfadan bir restoran seçin.
  4. Restoranın sayfasında 3e19beef78bb0d0e.png simgesini tıklayın.
  5. Bir yıldız puanı seçin.
  6. Yorum yazın.
  7. Gönder'i tıklayın. Yorumunuz, yorum listesinin en üstünde görünür.
  8. Cloud Firestore'da, Doküman ekle bölmesinde incelediğiniz restoranın dokümanlarını arayın ve seçin.
  9. Veri toplamaya başla bölmesinde değerlendirmeler'i seçin.
  10. Doküman ekle bölmesinde, incelemeniz için eklediğiniz dokümanı bulun ve beklenen şekilde eklendiğini doğrulayın.

Firestore Emulator&#39;daki dokümanlar

9. Kullanıcı tarafından yüklenen dosyaları web uygulamasından kaydetme

Bu bölümde, giriş yaptığınızda bir restoranla ilişkili resmi değiştirebilmeniz için işlev eklersiniz. Resmi Firebase Storage'a yükler ve restoranı temsil eden Cloud Firestore dokümanında resim URL'sini güncelleyebilirsiniz.

Kullanıcı tarafından yüklenen dosyaları web uygulamasından kaydetmek için aşağıdaki adımları uygulayın:

  1. src/components/Restaurant.jsx dosyasında, kullanıcı bir dosya yüklediğinde çalıştırılan kodu inceleyin:
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 });
}

Bu işlevde herhangi bir değişiklik yapmanız gerekmez ancak aşağıdaki adımlarda updateRestaurantImage() işlevinin davranışını uygularsınız.

  1. src/lib/firebase/storage.js dosyasında updateRestaurantImage() ve uploadImage() işlevlerini aşağıdaki kodla değiştirin:
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);
}

updateRestaurantImageReference() işlevi sizin için zaten uygulanmış. Bu işlev, Cloud Firestore'daki mevcut bir restoran dokümanındaki resim URL'sini güncellenmiş bir resim URL'siyle günceller.

Resim yükleme işlevini doğrulama

Resmin beklendiği gibi yüklendiğini doğrulamak için aşağıdaki adımları uygulayın:

  1. "Kullanıcıların her restoranın fotoğrafını değiştirmesine izin ver" commit mesajını içeren bir commit oluşturun ve GitHub deponuza aktarın.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  3. Web uygulamasında giriş yaptığınızı doğrulayın ve bir restoran seçin.
  4. 7067eb41fea41ff0.png simgesini tıklayın ve dosya sisteminizden bir resim yükleyin. Görüntünüz yerel ortamınızdan ayrılır ve Cloud Storage'a yüklenir. Resim, yüklendikten hemen sonra gösterilir.
  5. Firebase için Cloud Storage'a gidin.
  6. Restoranı temsil eden klasöre gidin. Yüklediğiniz resim klasörde mevcut.

6cf3f9e2303c931c.png

10. Üretken yapay zeka ile restoran yorumlarını özetleme

Bu bölümde, kullanıcıların her yorumu okumak zorunda kalmadan bir restoran hakkındaki genel fikri hızlıca anlayabilmesi için bir yorum özeti özelliği ekleyeceksiniz.

Cloud Secret Manager'da Gemini API anahtarı depolama

  1. Gemini API'yi kullanmak için bir API anahtarına ihtiyacınız vardır. Google AI Studio'yu ziyaret edin ve "API Anahtarı Oluştur"u tıklayın.
  2. "Google Cloud projelerinde arama yap" girişinde Firebase projenizi seçin. Her Firebase projesi, bir Google Cloud projesi tarafından desteklenir.
  3. Uygulama Barındırma, API anahtarları gibi hassas değerleri güvenli bir şekilde depolamanıza olanak tanımak için Cloud Secret Manager ile entegre çalışır:
    1. Terminalde yeni bir gizli anahtar oluşturmak için şu komutu çalıştırın:
    firebase apphosting:secrets:set GEMINI_API_KEY
    
    1. Gizli değer istendiğinde Google AI Studio'dan Gemini API anahtarınızı kopyalayıp yapıştırın.
    2. Yeni anahtarın üretim için mi yoksa yerel test için mi olduğu sorulduğunda "Üretim"i seçin.
    3. Arka uç hizmet hesabınızın gizliye erişebilmesi için erişim izni vermek isteyip istemediğiniz sorulduğunda "Evet"i seçin.
    4. Yeni gizli anahtarın apphosting.yaml'e eklenip eklenmeyeceği sorulduğunda kabul etmek için Y yazın.

Gemini API anahtarınız artık Cloud Secret Manager'da güvenli bir şekilde depolanır ve uygulama barındırma arka ucunuz tarafından erişilebilir.

Yorum özeti bileşenini uygulama

  1. src/components/Reviews/ReviewSummary.jsx içinde GeminiSummary işlevini aşağıdaki kodla değiştirin:
    export async function GeminiSummary({ restaurantId }) {
      const { firebaseServerApp } = await getAuthenticatedAppForUser();
      const reviews = await getReviewsByRestaurantId(
        getFirestore(firebaseServerApp),
        restaurantId
      );
    
      const reviewSeparator = "@";
      const prompt = `
        Based on the following restaurant reviews, 
        where each review is separated by a '${reviewSeparator}' character, 
        create a one-sentence summary of what people think of the restaurant. 
    
        Here are the reviews: ${reviews.map((review) => review.text).join(reviewSeparator)}
      `;
    
      try {
        if (!process.env.GEMINI_API_KEY) {
          // Make sure GEMINI_API_KEY environment variable is set:
          // https://firebase.google.com/docs/genkit/get-started
          throw new Error(
            'GEMINI_API_KEY not set. Set it with "firebase apphosting:secrets:set GEMINI_API_KEY"'
          );
        }
    
        // Configure a Genkit instance.
        const ai = genkit({
          plugins: [googleAI()],
          model: gemini20Flash, // set default model
        });
        const { text } = await ai.generate(prompt);
    
        return (
          <div className="restaurant__review_summary">
            <p>{text}</p>
            <p> Summarized with Gemini</p>
          </div>
        );
      } catch (e) {
        console.error(e);
        return <p>Error summarizing reviews.</p>;
      }
    }
    
  2. "Yorumları özetlemek için yapay zekadan yararlanın" commit mesajını içeren bir commit oluşturun ve GitHub deponuza gönderin.
  3. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni kullanıma sunma işleminizin tamamlanmasını bekleyin.
  4. Bir restoranın sayfasını açın. Sayfanın üst kısmında, sayfadaki tüm yorumların tek cümlelik bir özetini görürsünüz.
  5. Yeni bir yorum ekleyin ve sayfayı yenileyin. Özet değişecektir.

11. Sonuç

Tebrikler! Next.js uygulamasına özellik ve işlev eklemek için Firebase'i nasıl kullanacağınızı öğrendiniz. Özellikle aşağıdakileri kullandınız:

Daha fazla bilgi