Firebase'i Next.js uygulamasıyla entegre etme

1. Başlamadan önce

Bu codelab'de, Firebase'i Friendly Eats adlı bir Next.js web uygulamasıyla (restoran incelemeleri için bir web sitesi) nasıl entegre edeceğinizi öğreneceksiniz.

Friendly Eats web uygulaması

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

  • Otomatik derleme ve dağıtım: Bu codelab, yapılandırılmış bir dala her gönderim yaptığınızda Next.js kodunuzu otomatik olarak derlemek ve dağıtmak için Firebase App Hosting'i kullanır.
  • Oturum açma ve kapatma: Tamamlanan web uygulaması, Google ile oturum açmanıza ve oturumu kapatmanıza olanak tanır. Kullanıcı girişi ve kalıcılığı tamamen Firebase Authentication üzerinden yönetilir.
  • Resimler: Tamamlanan web uygulaması, oturum açmış kullanıcıların restoran resimlerini yüklemesine olanak tanır. Resim öğeleri Cloud Storage for Firebase'de depolanır. Firebase JavaScript SDK, yüklenen resimler için herkese açık bir URL sağlar. Bu herkese açık URL daha sonra Cloud Firestore'daki ilgili restoran belgesinde depolanır.
  • Yorumlar: Tamamlanan web uygulaması, oturum açmış kullanıcıların restoranlarla ilgili yorumlar yayınlamasına olanak tanır. Bu yorumlar yıldız puanı ve metin tabanlı bir mesajdan oluşur. Yorum bilgileri Cloud Firestore'da depolanır.
  • Filtreler: Tamamlanan 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 kullanılan filtrelere göre Firestore sorguları uygulanır.

Ön koşullar

  • GitHub hesabı
  • Next.js ve JavaScript bilgisi

Neler öğreneceksiniz?

  • Firebase'i Next.js uygulama yönlendiricisi ve sunucu taraflı oluşturma ile kullanma
  • Firebase için Cloud Storage'da görüntüleri kalıcı hale getirme
  • Cloud Firestore veritabanında verileri okuma ve yazma
  • Google ile oturum açma özelliğini Firebase JavaScript SDK ile kullanma

Gerekenler

  • Git
  • Node.js'nin son kararlı sürümü
  • Google Chrome gibi istediğ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

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

Bu codelab'de uygulamanın başlangıç kod tabanı sağlanır ve Firebase CLI kullanılır.

GitHub deposu oluşturma

Codelab kaynağını https://github.com/firebase/friendlyeats-web adresinde bulabilirsiniz. Depoda birden fazla platform için örnek projeler bulunur. Ancak bu codelab'de yalnızca nextjs-start dizini kullanılır. Aşağıdaki dizinlere dikkat edin:

* `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. Terminali 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ü getirmek için giget npm paketini kullanın:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
    
  3. Değişiklikleri yerel olarak Git ile 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ı verebilirsiniz.
  5. GitHub'ın sizin için oluşturduğu yeni URL'yi kopyalayın. Aşağıdakilerden biri gibi görünür:
    • 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 tutucusu yerine gerçek depo URL'nizi kullanın.
    git remote add origin <REPOSITORY_URL>
    
    git push -u origin main
    
  7. Başlangıç kodunu artık GitHub deponuzda görmeniz gerekir.

Firebase CLI'yı yükleme veya güncelleme

Firebase CLI'nın yüklendiğini ve 14.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ş yapın.

  1. Firebase CLI'de oturum açmak 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 girin.
  3. Tarayıcınızda Google Hesabınızı seçin ve İzin ver'i tıklayın.

3. Firebase projenizi oluşturma

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

Firebase projesi oluşturma

  1. Önceki adımda kullandığınız Google Hesabı ile Firebase konsolunda oturum açın.
  2. Yeni bir proje oluşturmak için düğmeyi tıklayın ve ardından bir proje adı girin (örneğin, FriendlyEats Codelab).
  3. Devam'ı tıklayın.
  4. İstenirse Firebase şartlarını inceleyip kabul edin ve Devam'ı tıklayın.
  5. (İsteğe bağlı) Firebase konsolunda yapay zeka yardımını etkinleştirin ("Firebase'de Gemini" olarak adlandırılır).
  6. Bu codelab için Google Analytics'e ihtiyacınız yoktur. Bu nedenle, Google Analytics seçeneğini devre dışı bırakın.
  7. Proje oluştur'u tıklayın, projenizin hazırlanmasını bekleyin ve ardından Devam'ı tıklayın.

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

Firebase App Hosting ve Firebase için Cloud Storage'ı kullanmak istiyorsanız Firebase projenizin kullandıkça öde (Blaze) fiyatlandırma planında olması gerekir. Bu da projenin bir Cloud Faturalandırma Hesabı'na bağlı olduğu anlamına gelir.

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

  1. Firebase konsolunda planınızı yükseltmeyi seçin.
  2. Blaze planını seçin. Bir Cloud Faturalandırma hesabını projenize 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 Proje genel bakış'a gidin ve e41f2efdd9539c31.png Web'i tıklayın.

    Projenizde kayıtlı uygulamalarınız varsa Web simgesini görmek için Uygulama ekle'yi tıklayın.
  2. Uygulama takma adı metin kutusuna My Next.js app gibi hatırlanabilir bir uygulama takma adı girin.
  3. Bu uygulama için Firebase Hosting'i de ayarlayın onay kutusunu işaretlenmemiş olarak bırakın.
  4. Uygulamayı kaydet > Konsola git'i tıklayın.

Firebase konsolunda Firebase hizmetlerini ayarlama

Kimlik doğrulama ayarlama

  1. Firebase konsolunda Authentication'a 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 Build'i (Oluştur) genişletin ve Firestore Database'i (Firestore Veritabanı) seçin.
  2. Create database'i (Veritabanı oluştur) tıklayın.
  3. Veritabanı Kimliği'ni (default) olarak bırakın.
  4. Veritabanınız 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 codelab'in ilerleyen bölümlerinde, verilerinizin güvenliğini sağlamak için güvenlik kuralları ekleyeceksiniz. Veritabanınıza güvenlik kuralları eklemeden uygulamayı herkese açık şekilde dağıtmayın veya herkese açık olarak kullanıma sunmayın.
  6. Oluştur'u tıklayın.

Cloud Storage for Firebase'i ayarlama

  1. Firebase konsolunun sol panelinde Build'i (Oluştur) genişletin ve Storage'ı (Depolama) seçin.
  2. Başlayın'ı tıklayın.
  3. Varsayılan depolama paketinize bir konum seçin.
    US-WEST1, US-CENTRAL1 ve US-EAST1 bölgelerindeki paketler, Google Cloud Storage için "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 codelab'in ilerleyen bölümlerinde, verilerinizin güvenliğini sağlamak için güvenlik kuralları ekleyeceksiniz. Depolamapaketinize güvenlik kuralları eklemeden uygulamayı herkese açık olarak dağıtmayın veya kullanıma sunmayın.
  5. Oluştur'u tıklayın.

Güvenlik kurallarını dağıtma

Kodda, Firestore ve Firebase için Cloud Storage'e yönelik güvenlik kuralı kümeleri zaten vardır. Güvenlik Kurallarını dağıttıktan sonra, veritabanınızdaki ve paketinizeki veriler kötüye kullanıma karşı daha iyi korunur.

  1. Terminalinizde, CLI'yı daha önce oluşturduğunuz Firebase projesini kullanacak şekilde yapılandırın:
    firebase use --add
    
    Takma ad istendiğinde friendlyeats-codelab girin.
  2. Bu güvenlik kurallarını (ve daha sonra gerekli olacak dizinleri) dağıtmak için terminalinizde şu komutu çalıştırın:
    firebase deploy --only firestore,storage
    
  3. "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" sorusu sorulursa 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, başlıklar, restoran bilgileri ve yorumlar için React bileşenleri

src/lib

Mutlaka 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 simgeler gibi statik öğeler

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'e özgü yapılandırma (sunucu işlemleri etkinleştirilir)

jsconfig.json

JavaScript dil hizmeti yapılandırması

Sunucu ve istemci bileşenleri

Uygulama, App Router'ı kullanan bir Next.js web uygulamasıdır. Uygulamanın her yerinde sunucu oluşturma 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şında "use client" yönergesiyle belirtilen bir istemci bileşenidir.

Ekstreleri içe aktarma

Aşağıdakilere benzer içe aktarma ifadeleri görebilirsiniz:

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

Uygulama, hantal göreli içe aktarma yollarını önlemek için @ sembolünü 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. Daha sonra tek tek 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 bir araya getirilir.

5. App Hosting arka ucu oluşturma

Bu bölümde, Git deponuzdaki bir dalı izlemek için App Hosting arka ucu ayarlayacaksınız.

Bu bölümün sonunda, GitHub'daki deponuza bağlı bir App Hosting arka ucunuz olacak. Bu arka uç, main dalınıza yeni bir taahhüt gönderdiğinizde uygulamanızın yeni bir sürümünü otomatik olarak yeniden oluşturup kullanıma sunacak.

Arka uç oluşturma

  1. Firebase konsolunda Uygulama Hosting sayfası'na gidin:

&quot;Başlayın&quot; düğmesiyle birlikte Uygulama Barındırma Konsolu&#39;nun sıfır durumu

  1. Arka uç oluşturma akışını başlatmak için "Başlayın"ı tıklayın. Arka uçunuzu 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 deposunu içe aktarma" adımındaki istemleri uygulayın.
  4. Dağıtım ayarlarını belirleyin:
    1. Kök dizini / olarak tutun.
    2. Canlı dalı main olarak ayarlayın.
    3. Otomatik kullanıma sunma işlemlerini etkinleştirme
  5. Arka uç paketinizi adlandırın friendlyeats-codelab.
  6. "Firebase web uygulaması ilişkilendirin" bölümünde "Yeni Firebase web uygulaması oluşturun"u tıklayın.
  7. "Bitir ve dağıt"ı tıklayın. Kısa bir süre sonra, yeni uygulama barındırma arka uçunuzun 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ılımı nedeniyle çalışmaya başlaması birkaç dakika sürebilir.
  9. Hay aksi! 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, App Hosting arka uçunuzun "Günlükler" sekmesini kontrol edin. "Hata: uygulanmadı" günlüğünü görürsünüz. Kimlik doğrulama eklediğimizde bu sorunu sonraki adımda düzelteceğiz.

İlk web uygulamanızı dağıttınız. GitHub deponuzun main dalına her yeni kaydetme işlemini aktardığınızda Firebase konsolunda yeni bir derleme ve dağıtımın 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 kimlik doğrulama ekleyerek uygulamaya giriş yapabilirsiniz.

Yetkilendirilen alan ekleyin

Firebase Authentication yalnızca izin verdiğiniz alanlardan gelen oturum açma isteklerini kabul eder. Burada, App Hosting arka uçunuzun alanını projenizdeki onaylı alanlar listesine ekleyeceğiz.

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

Oturum açma ve oturum 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 oturumunu kapatır.

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

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 sunucuda yansıtmak için FirebaseServerApp'i kullanacağız.

src/lib/firebase/serverApp.js dosyasını açın ve 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ı bir özellik olarak geçirir.

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

Bu, <Header> bileşeninin, varsa kullanıcı verilerini sunucu çalışma zamanında oluşturduğu anlamına gelir. Sayfa ilk yüklendikten sonra sayfa yaşam döngüsü sırasında kimlik doğrulama güncellemeleri olursa onAuthStateChanged işleyici bunları yönetir.

Şimdi yeni bir derleme yayınlamanın ve oluşturduklarınızı doğrulamanın zamanı.

  1. "Add authentication" (Kimlik doğrulama ekle) adlı commit mesajıyla bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın 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. Sunucudan döndürülen ham HTML kaynağında görünür.

7. Restoran bilgilerini görüntüleme

Web uygulamasında restoranlar ve yorumlar için örnek veriler yer alır.

Bir veya daha fazla restoran ekleme

Yerel Cloud Firestore veritabanınıza sahte 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 restoranlar ekle'yi seçin.
  2. Firebase konsolundaki Firestore Database (Firestore Veritabanı) sayfasında restaurants'ı (restoranlar) seçin. Restoran koleksiyonundaki üst düzey dokümanları görürsünüz. Bu dokümanların her biri bir restoranı temsil eder.
  3. Bir restoran dokümanının özelliklerini keşfetmek için birkaç dokümanı tıklayın.

Restoran listesini görüntüleme

Cloud Firestore veritabanınızda artık Next.js web uygulamasının gösterebileceğ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 restoran listesini alan getRestaurants işlevine yapılan çağrıyı inceleyin. getRestaurants işlevini aşağıdaki adımlarda uygulayacaksı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. "Read the list of restaurants from Firestore" (Firestore'dan restoran listesini oku) adlı commit mesajıyla bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın tamamlanmasını bekleyin.
  3. Web uygulamasında sayfayı yenileyin. Restoran resimleri sayfada bloklar halinde gösterilir.

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

Next.js çerçevesi kullanılırken verilerin sunucu çalışma zamanında mı yoksa istemci tarafı çalışma zamanında mı yüklendiği anlaşılmayabilir.

Restoran girişlerinin 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.

Geliştirici Araçları&#39;nda JavaScript&#39;i devre dışı bırakma

  1. Web uygulamasını yenileyin. Restoran listeleri yine de yüklenir. Restoran bilgileri, sunucu yanıtında döndürülür. JavaScript etkinleştirildiğinde restoran bilgileri, istemci tarafındaki JavaScript kodu aracılığıyla doldurulur.
  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örmüştü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 dolduracak şekilde yapılandırılabilir.

Sunucu tarafında oluşturulan işaretlemeyi doldurmak için src/components/RestaurantListings.jsx dosyasını yapılandırmak üzere aşağıdaki adımları uygulayın:

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

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

  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 Database sayfası üzerinden yapılan değişiklikler artık web uygulamasına gerçek zamanlı olarak yansıtılıyor.

  1. "Listen for realtime restaurant updates" (Anlık restoran güncellemelerini dinle) mesajıyla bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın tamamlanmasını bekleyin.
  3. Web uygulamasında 27ca5d1e8ed8adfe.png > Örnek restoranlar ekle'yi seçin. Anlık görüntü işleviniz doğru şekilde uygulanmışsa restoranlar, sayfa yenilenmeden anlık olarak görünür.

8. Web uygulamasından gönderilen kullanıcı yorumlarını 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 hesaplanan ortalama 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 kullanışlı bir API sağlar. Örneğin, form gönderimi yükünden metin değerini almak için data.get("text") kullanılır.

Yorum formu gönderimini işlemek için Next.js Server Action kullanmak istiyorsanız aşağıdaki adımları uygulayın:

  1. src/components/ReviewDialog.jsx dosyasında, <form> öğesindeki 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 için yorum ekleme

Yorum gönderimleriyle ilgili destek uyguladınız. Artık yorumlarınızın Cloud Firestore'a doğru şekilde eklendiğini doğrulayabilirsiniz.

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

  1. "Allow users to submit restaurant reviews" (Kullanıcıların restoran yorumu göndermesine izin ver) mesajıyla bir commit oluşturun ve bunu GitHub deponuza gönderin.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın 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. 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, Add document (Belge ekle) bölmesinde incelediğiniz restoranın belgesini arayın ve seçin.
  9. Koleksiyonu başlat bölmesinde puanlar'ı seçin.
  10. Belge ekle bölmesinde, incelemeniz için olan belgeyi bulun ve beklendiği gibi eklenip eklenmediğini doğrulayın.

Firestore Emulator&#39;daki dokümanlar

9. Web uygulamasından kullanıcı tarafından yüklenen dosyaları kaydetme

Bu bölümde, oturum açtığınızda bir restoranla ilişkili resmi değiştirebilmeniz için işlevsellik ekleyeceksiniz. Resmi Firebase Storage'a yüklersiniz ve restoranı temsil eden Cloud Firestore belgesindeki resim URL'sini güncellersiniz.

Web uygulamasında kullanıcı tarafından yüklenen dosyaları 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ışan 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 updateRestaurantImage() işlevinin davranışını aşağıdaki adımlarda uygulayabilirsiniz.

  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'da mevcut bir restoran dokümanını 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. "Allow users to change each restaurants' photo" (Kullanıcıların her restoranın fotoğrafını değiştirmesine izin ver) mesajını içeren bir commit oluşturun ve bunu GitHub deponuza aktarın.
  2. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın 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. Resminiz yerel ortamınızdan ayrılır ve Cloud Storage'a yüklenir. Resim, yükledikten hemen sonra görünür.
  5. Firebase için Cloud Storage'a gidin.
  6. Restoranı temsil eden klasöre gidin. Yüklediğiniz resim klasörde bulunur.

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 görüşleri hızlıca anlaması için yorum özeti özelliği ekleyeceksiniz.

Cloud Secret Manager'da Gemini API anahtarı depolama

  1. Gemini API'yi kullanmak için 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 ara" 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 olur:
    1. Terminalde yeni bir gizli anahtar oluşturma komutunu çalıştırın:
    firebase apphosting:secrets:set GEMINI_API_KEY
    
    1. Gizli değer istendiğinde Google AI Studio'daki Gemini API anahtarınızı kopyalayıp yapıştırın.
    2. Yeni sırrın üretim veya yerel test için olup olmadığı sorulduğunda "Üretim"i seçin.
    3. Arka uçtaki hizmet hesabınızın gizli diziye erişebilmesi için erişim izni vermek isteyip istemediğiniz sorulduğunda "Evet"i seçin.
    4. Yeni gizli anahtarın apphosting.yaml'ya 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 saklanıyor ve App Hosting arka ucunuz tarafından erişilebiliyor.

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. "Use AI to summarize reviews" (Yorumları özetlemek için yapay zekayı kullan) yorum mesajıyla bir commit oluşturun ve bunu GitHub deponuza gönderin.
  3. Firebase konsolunda Uygulama Barındırma sayfasını açın ve yeni dağıtımınızın tamamlanmasını bekleyin.
  4. Bir restoranın sayfasını açın. En üstte, 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şikliğini görmeniz gerekir.

11. Sonuç

Tebrikler! Firebase'i kullanarak Next.js uygulamasına nasıl özellik ve işlev ekleyeceğinizi öğrendiniz. Özellikle aşağıdaki özellikleri kullandınız:

Daha fazla bilgi