Firebase'i Next.js uygulamasıyla entegre etme

1. Başlamadan önce

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

Friendly Eats web uygulaması

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

  • Otomatik derleme ve dağıtma: Bu codelab, yapılandırılmış bir dala her aktarma işleminizde Next.js kodunuzu otomatik olarak oluşturmak ve dağıtmak için Firebase Uygulama Barındırma'yı kullanır.
  • Oturum açma ve çıkış yapma: 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 ile yönetilir.
  • Resimler: Tamamlanmış web uygulaması, oturum açmış kullanıcıların restoran resimleri yükleyebilmesini sağlar. Resim öğeleri Cloud Storage for Firebase'de saklanı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 saklanır.
  • Yorumlar: Tamamlanan web uygulaması, oturum açmış kullanıcıların yıldız puanı ve metin tabanlı bir mesajdan oluşan restoranlar hakkında yorum yayınlamasına olanak tanır. İnceleme bilgileri Cloud Firestore'da saklanır.
  • Filtreler: Tamamlanan web uygulaması, oturum açmış kullanıcıların restoran listesini kategoriye, konuma ve fiyata göre filtrelemesini sağlar. Kullanılan sıralama yöntemini de özelleştirebilirsiniz. Verilere Cloud Firestore'dan erişilebilir ve Firestore sorguları, kullanılan filtrelere göre uygulanır.

Ön koşullar

  • GitHub hesabı
  • Next.js ve JavaScript bilgisi

Neler öğreneceksiniz?

  • Firebase'i Next.js Uygulama Yönlendiricisi ve sunucu tarafı oluşturma ile kullanma.
  • Firebase için Cloud Storage'da görüntülerin kalıcı olmasını sağlama.
  • Cloud Firestore veritabanında veri okuma ve yazma
  • Firebase JavaScript SDK ile Google ile oturum açma özelliğini kullanma

Gerekenler

  • Git
  • Node.js'nin yeni kararlı sürümü
  • Google Chrome gibi istediğiniz bir tarayıcı
  • Kod düzenleyici ve terminali olan bir geliştirme ortamı
  • Firebase projenizin oluşturulması ve yönetilmesi için kullanılan bir Google hesabı
  • Firebase projenizi Blaze fiyatlandırma planına yükseltme olanağı

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

Bu codelab, uygulamanın başlangıç kod tabanını sağlar ve Firebase CLI'yı 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 codelab yalnızca nextjs-start dizinini kullanı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. Bir 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ü getirmek için giget npm paketini kullanın:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
    
  3. Değişiklikleri git:
    git init
    
    git commit -a -m "codelab starting point"
    
    git branch -M main
    
    ile yerel olarak izleyin
  4. Yeni bir GitHub deposu oluşturun: https://github.com/new. İstediğiniz adı verin.
    1. GitHub, https://github.com//.git veya git@github.com:/.git gibi görünen yeni bir kod deposu URL'si sağlayacak. Bu URL'yi kopyalayın.
  5. Yerel değişiklikleri yeni GitHub deponuza aktarın. Kod deposu URL'nizi yer tutucusuyla değiştirerek aşağıdaki komutu çalıştırın.
    git remote add origin <your-repository-url>
    
    git push -u origin main
    
  6. GitHub deponuzda başlangıç kodunu artık görüyor olmalısınız.

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

Firebase CLI'ın yüklü olduğunu ve v13.9.0 veya sonraki bir sürüme sahip 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'ya giriş yapmak için şu komutu çalıştırın:
    firebase login
    
  2. Firebase'in veri toplamasını istediğinize bağlı olarak Y veya N girin.
  3. Tarayıcınızda Google hesabınızı seçip Allow'u (İzin ver) tıklayın.

3. Firebase projenizi oluşturma

Bu bölümde Firebase projesi oluşturup Firebase web uygulamasını bu projeyle ilişkilendireceksiniz. Örnek web uygulaması tarafından kullanılan Firebase hizmetlerini de ayarlayacaksınız.

Firebase projesi oluşturun

  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ını) girip Devam'ı tıklayın.
  3. Firebase faturalandırma planını onaylayın iletişim kutusunda planın Blaze olduğunu onaylayın ve ardından Planı onayla'yı tıklayın.
  4. Bu codelab için Google Analytics'e ihtiyacınız yoktur. Bu nedenle, Bu proje için Google Analytics'i etkinleştir seçeneğini kapalı duruma getirin.
  5. Create project (Proje oluştur) seçeneğini tıklayın.
  6. Projenizin temel hazırlığının yapılmasını bekleyin ve ardından Devam'ı tıklayın.
  7. Firebase projenizde Proje Ayarları'na gidin. Daha sonra ihtiyacınız olacağından proje kimliğinizi not edin. Bu benzersiz tanımlayıcı, projenizin tanımlanma şeklidir (örneğin, Firebase CLI'da).

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

Uygulama Barındırma'yı kullanmak için Firebase projenizin Blaze fiyatlandırma planı kapsamında olması, yani Cloud Faturalandırma Hesabı ile ilişkilendirilmiş olması gerekir.

  • Cloud Faturalandırma 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ı için uygun olup olmadığınızı kontrol edin.

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

  1. Firebase konsolunda planınızı yükseltmeyi seçin.
  2. İletişim kutusunda Blaze planını seçin, ardından ekrandaki talimatları uygulayarak projenizi bir Cloud Faturalandırma Hesabı ile ilişkilendirin.
    Cloud Faturalandırma Hesabı oluşturmanız gerekiyorsa yükseltme işlemini tamamlamak için Firebase konsolundaki yükseltme akışına geri dönmeniz gerekebilir.

Firebase projenize bir web uygulaması ekleyin

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

    Projenizde zaten 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 ayarla onay kutusunu işaretlemeden bırakın.
  4. Uygulamayı kaydet > İleri > İleri > Konsola devam et'i tıklayın.

Firebase konsolunda Firebase hizmetlerini ayarlama

Kimlik doğrulamayı ayarla

  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. Proje için herkese açık ad metin kutusuna My Next.js app gibi akılda kalıcı bir ad girin.
  5. Proje için destek e-posta adresi açılır menüsünden e-posta adresinizi seçin.
  6. Kaydet'i tıklayın.

Cloud Firestore kurulumu

  1. Firebase konsolunda Firestore'a gidin.
  2. Veritabanı oluştur > İleri > Test modunda başlat > İleri'yi tıklayın.
    Bu codelab'in ilerleyen bölümlerinde, verilerinizin güvenliğini sağlamak için Güvenlik Kuralları ekleyeceksiniz. Veritabanınız için Güvenlik Kuralları eklemeden bir uygulamayı herkese açık olarak kullanıma dağıtmayın.
  3. Varsayılan konumu kullanın veya tercih ettiğiniz bir konumu seçin.
    Gerçek bir uygulama için kullanıcılarınıza yakın bir konum seçmeniz gerekir. Bu konumun daha sonra değiştirilemeyeceğini ve otomatik olarak varsayılan Cloud Storage paketinizin konumu olacağını unutmayın (sonraki adım).
  4. Done'ı (Bitti) tıklayın.

Cloud Storage for Firebase kurulumu

  1. Firebase konsolunda Depolama alanı'na gidin.
  2. Başlayın > Test modunda başlat > İleri'yi tıklayın.
    Bu codelab'in ilerleyen bölümlerinde verilerinizin güvenliğini sağlamak için Güvenlik Kuralları ekleyeceksiniz. Depolama paketiniz için Güvenlik Kuralları eklemeden bir uygulamayı herkese açık olarak kullanıma dağıtmayın.
  3. Paketinizin konumu önceden seçilmiş olmalıdır (önceki adımda Firestore kurulduğundan).
  4. Done'ı (Bitti) tıklayın.

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

Bu bölümde, uygulamanın başlangıç kod tabanında bulunan ve bu codelab'de işlevsellik ekleyeceğiniz birkaç alanı 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 ayrıntıları ve yorumlar için tepki bileşenleri

src/lib

React veya Next.js'ye bağlı olması gerekmeyen yardımcı program işlevleri

src/lib/firebase

Firebase'e özel kod ve Firebase yapılandırması

public

Web uygulamasındaki simgeler gibi statik öğeler

src/app

Next.js Uygulama Yönlendiricisi ile Yönlendirme

src/app/restaurant

API rota işleyicisi

package.json ve package-lock.json

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

next.config.js

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

jsconfig.json

JavaScript dil hizmeti yapılandırması

Sunucu ve istemci bileşenleri

Uygulama, Uygulama Yönlendiricisi'ni 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şında "use client" yönergesiyle belirtilen bir istemci bileşenidir.

İfadeleri içe aktar

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

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

Uygulama, kullanışsız göreli içe aktarma yollarından kaçınmak için @ simgesini kullanır ve bunu yol takma adları ile mümkün kılar.

Firebase'e özel API'ler

Tüm Firebase API kodları src/lib/firebase dizininde sarmalanır. Firebase işlevlerini doğrudan içe aktarmak yerine bağımsız React bileşenleri daha sonra sarmalanmış işlevleri src/lib/firebase dizininden içe aktarır.

Sahte veri

Sahte restoran ve yorum verileri src/lib/randomData.js dosyasında yer alıyor. 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 ayarlayacaksınız.

Bu bölümün sonunda, main şubenize yeni bir kayıt aktardığınızda uygulamanızın yeni bir sürümünü otomatik olarak yeniden derleyip kullanıma sunacak olan, GitHub'daki kod deponuza bağlı bir App Hosting arka ucuna sahip olacaksınız.

Güvenlik Kurallarını Dağıtma

Kodda Firestore ve Cloud Storage for Firebase için güvenlik kuralı grupları zaten 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, KSA'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ı dağıtmak için terminalinizde şu komutu çalıştırın:
    firebase deploy --only firestore:rules,storage
    
  3. "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" sorusu sorulursa Enter tuşuna basarak Evet'i seçin.

Firebase yapılandırmanızı web uygulaması kodunuza ekleyin

  1. Firebase konsolunda Proje ayarları'na gidin.
  2. Yeni bir web uygulaması kaydetmek için SDK kurulumu ve yapılandırması bölmesinde "Uygulama ekle"yi, ardından kod ayraçlarını tıklayın.
  3. Web uygulaması oluşturma akışının sonunda firebaseConfig değişkenini kopyalayıp özelliklerini ve ilgili değerleri kopyalayın.
  4. Kod düzenleyicinizde apphosting.yaml dosyasını açın ve ortam değişkeni değerlerini Firebase konsolundaki yapılandırma değerleriyle doldurun.
  5. Dosyadaki mevcut özellikleri, kopyaladığınız özelliklerle değiştirin.
  6. Dosyayı kaydedin.

Arka uç oluşturma

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

App Hosting konsolunun sıfır durumu ve bir &quot;Başlayın&quot; düğmesi

  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. Daha önce oluşturduğunuz GitHub deposunu bağlamak için ilk adımdaki talimatları uygulayın.
  3. Dağıtım ayarlarını yapın:
    1. Kök dizin / olarak kalsın
    2. Canlı dalı main olarak ayarlayın
    3. Otomatik kullanıma sunmaları etkinleştir
  4. Arka ucunuza friendlyeats-codelab ad verin.
  5. "Firebase web uygulaması oluşturun veya ilişkilendirin" bölümünde, "Mevcut bir Firebase web uygulamasını seçin" açılır menüsünden daha önce yapılandırdığınız web uygulamasını seçin.
  6. "Bitir ve dağıt"ı tıklayın. Kısa bir süre sonra, yeni App Hosting arka ucunuzun durumunu görebileceğiniz yeni bir sayfaya yönlendirileceksiniz!
  7. Kullanıma sunma işleminiz tamamlandıktan sonra "domains" (alanlar) bölümünde ücretsiz alanınızı tıklayın. DNS yayılımı nedeniyle bunun çalışmaya başlaması birkaç dakika sürebilir.

İlk web uygulamasını dağıttınız. GitHub deponuzun main dalına her yeni kayıt gönderdiğinizde, Firebase konsolunda yeni bir derleme ve kullanıma sunma işleminin başladığını görürsünüz. Kullanıma sunma işlemi tamamlandığında siteniz otomatik olarak güncellenir.

6. Web uygulamasına kimlik doğrulama ekleme

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

Oturum açma ve kapatma işlevlerini uygulama

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

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

Firebase API'si

Açıklama

GoogleAuthProvider

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

signInWithPopup

İletişim kutusu tabanlı kimlik doğrulama akışı başlatır.

auth.signOut

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

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

  1. "Insert Google Authentication" (Google Kimlik Doğrulaması Ekleme) kayıt mesajını içeren bir kayıt oluşturun ve bu kaydı GitHub deponuza aktarın. 1. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin tamamlanmasını bekleyin.
  2. Web uygulamasında sayfayı yenileyin ve Sign in with Google (Google ile oturum aç) seçeneğini tıklayın. Web uygulaması güncellenmediğinden oturum açma işleminin başarılı olup olmadığı anlaşılmıyor.

Kimlik doğrulama durumunu sunucuya gönder

Kimlik doğrulama durumunu sunucuya iletmek için Service Worker kullanırız. fetchWithFirebaseHeaders ve getAuthIdToken işlevlerini aşağıdaki kodla değiştirin:

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

Sunucuda kimlik doğrulama durumunu okuma

İstemcinin sunucudaki kimlik doğrulama durumunu yansıtmak için FirebaseServerApp'i kullanacağız.

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

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

Kimlik doğrulama değişikliklerine abone ol

Kimlik doğrulama değişikliklerine abone olmak için aşağıdaki adımları uygulayın:

  1. src/components/Header.jsx dosyasına gidin.
  2. useUserSession işlevini aşağıdaki kodla değiştirin:
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;
}

Bu kod, onAuthStateChanged işlevi kimlik doğrulama durumunda bir değişiklik olduğunu belirttiğinde kullanıcıyı güncellemek için bir React durum kancası kullanır.

Değişiklikleri doğrulayın

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

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

Yani <Header> bileşeni, sunucu çalışma süresinde kullanıcı verilerini (varsa) oluşturur. İlk sayfa yüklendikten sonra sayfa yaşam döngüsü boyunca kimlik doğrulama güncellemeleri varsa onAuthStateChanged işleyici bunları işler.

Şimdi yeni bir derlemeyi kullanıma sunma ve oluşturduğunuz projeyi doğrulama zamanı.

  1. "Show signin status" (Oturum açma durumunu göster) kayıt mesajıyla bir kayıt oluşturup GitHub deponuza aktarın.
  2. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin 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 başlıkta görünecektir.
    2. Oturumu kapatıp tekrar açın. Sayfa, sayfa yenilenmeden gerçek zamanlı olarak güncellenir. Bu adımı farklı kullanıcılar için 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öster

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

Bir veya daha fazla restoran ekleyin

Sahte restoran verilerini yerel Cloud Firestore veritabanınıza eklemek için aşağıdaki adımları uygulayın:

  1. Web uygulamasında 2cf67d488d8e6332.png > Örnek restoran ekle'yi seçin.
  2. Firebase konsolunda Firestore Database sayfasında restoranlar'ı seçin. Restoran koleksiyonunda üst düzey belgeleri görürsünüz. 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öster

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 şu adımları izleyin:

  1. src/app/page.js dosyasında, <Home /> sunucu bileşenini bulun ve sunucunun çalışma zamanında restoranların listesini getiren getRestaurants işlevine yapılan çağrıyı inceleyin. getRestaurants işlevini aşağıdaki adımlarda uygulayabilirsiniz.
  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 windows from Firestore" (Firestore'daki restoranlar listesini oku) kayıt mesajıyla bir kayıt oluşturun ve GitHub deponuza aktarın.
  2. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin tamamlanmasını bekleyin.
  3. Web uygulamasında sayfayı yenileyin. Restoran resimleri, sayfada karolar olarak görünür.

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

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

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 hâlâ yüklenmeye devam ediyor. Restoran bilgileri, sunucu yanıtında döndürülür. JavaScript etkinleştirildiğinde, restoran bilgileri istemci taraflı JavaScript kodu aracılığıyla kaynaklardan yararlanılarak sağlanır.
  2. Geliştirici Araçları'nda JavaScript'i yeniden etkinleştirin.

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

Ö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 dahil sunucuda oluşturulur.

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

src/components/RestaurantListings.jsx dosyasını sunucu tarafından oluşturulan işaretlemeyi kullanacak şekilde yapılandırmak için şu adımları uygulayın:

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

        return () => {
                unsubscribe();
        };
}, [filters]);

Bu kod, önceki adımda uyguladığınız getRestaurants() işlevine benzeyen getRestaurantsSnapshot() işlevini çağırır. Ancak bu anlık görüntü işlevi, restoranın koleksiyonunda her değişiklik yapıldığında geri çağırmanın ç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);

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

Firestore Veritabanı sayfasında yapılan değişiklikler artık web uygulamasına gerçek zamanlı olarak yansıtılır.

  1. "Gerçek zamanlı restoran güncellemelerini dinle" kayıt mesajıyla bir kayıt oluşturun ve bunu GitHub deponuza aktarın.
  2. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin 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 gerçek zamanlı olarak görüntülenir.

8. Kullanıcıların web uygulamasından gönderdiği yorumları 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 belgesi ekler. Kod ayrıca restoranı temsil eden mevcut Firestore dokümanını puan sayısı ve hesaplanan ortalama puan açısından 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 İşlemini Uygulama

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

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

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

action özellik değeri, 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"),
        });
}

Bir restoran için yorum ekleme

İnceleme gönderimleri için destek sağladınız. Artık yorumlarınızın Cloud Firestore'a doğru şekilde eklendiğini doğrulayabilirsiniz.

İnceleme eklemek ve incelemenin 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" kayıt mesajıyla bir kayıt oluşturun ve bu kaydı GitHub deponuza aktarın.
  2. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin tamamlanmasını bekleyin.
  3. Web uygulamasını yenileyin ve ana sayfadan bir restoran seçin.
  4. Restoranın sayfasında 3e19beef78bb0d0e.png'i tıklayın.
  5. Yıldız puanı seçin.
  6. Yorum yazın.
  7. Gönder'i tıklayın. Yorumunuz, yorumlar listesinin en üstünde görünür.
  8. Cloud Firestore'da, Belge ekle bölmesinde, incelediğiniz restoran belgesini bulup seçin.
  9. Koleksiyonu başlat bölmesinde derecelendirmeler'i seçin.
  10. Doküman ekle bölmesinde, beklendiği gibi eklendiğini doğrulamak için incelemeniz gereken dokümanı bulun.

Firestore Emulator&#39;daki belgeler

9. Web uygulamasından kullanıcı tarafından yüklenen dosyaları 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 belgesindeki resim URL'sini güncellersiniz.

Kullanıcıların web uygulamasından yüklediği dosyaları kaydetmek için şu adımları uygulayın:

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

Değişiklik gerekmez ancak aşağıdaki adımlarda updateRestaurantImage() işlevinin davranışını 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'daki mevcut bir restoran dokümanını güncellenmiş bir resim URL'si ile 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" kayıt iletisiyle bir kayıt oluşturun ve bu kaydı GitHub deponuza aktarın.
  2. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin tamamlanmasını bekleyin.
  3. Web uygulamasında, giriş yaptığınızı doğrulayın ve bir restoran seçin.
  4. 7067eb41fea41ff0.png'i tıklayın ve dosya sisteminizden bir resim yükleyin. Görüntünüz yerel ortamınızdan çıkar ve Cloud Storage'a yüklenir. Resim yüklendikten 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 mevcut.

6cf3f9e2303c931c.png

10. Restoran yorumlarını üretken yapay zeka ile özetleme

Bu bölümde, kullanıcının bir restoran hakkında herkesin ne düşündüğünü, her yorumu okumak zorunda kalmadan hızlı bir şekilde anlayabilmesi için bir yorum özeti özelliği ekleyeceksiniz.

Cloud Secret Manager'da Gemini API anahtarı saklama

  1. Gemini API'yi kullanmak için API anahtarı gerekir. Google AI Studio'da anahtar oluşturun.
  2. App Hosting, API anahtarları gibi hassas değerleri güvenli bir şekilde saklamanızı sağlamak için Cloud Secret Manager ile entegre olarak çalışır:
    1. Bir terminalde, yeni bir gizli anahtar oluşturmak için şu komutu çalıştırın:
    firebase apphosting:secrets:set gemini-api-key
    
    1. Gizli anahtar değeri istendiğinde Google AI Studio'dan Gemini API anahtarınızı kopyalayıp yapıştırın.
    2. Yeni gizli anahtarın apphosting.yaml hizmetine eklenmesi gerekip gerekmediğ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 depolanmaktadır ve App Hosting arka ucunuz tarafından erişilebilir.

Yorum özeti bileşenini uygulama

  1. src/components/Reviews/ReviewSummary.jsx öğesinde GeminiSummary işlevini şu kodla değiştirin:
    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>;
        }
    }
    
  2. "Yorumları özetlemek için AI'ı kullanın" kayıt mesajıyla bir kayıt oluşturun ve bu kaydı GitHub deponuza aktarın.
  3. Firebase konsolunda App Hosting (Uygulama Barındırma) sayfasını açın ve yeni kullanıma sunma sürecinizin tamamlanmasını bekleyin.
  4. Bir restoran sayfasını açın. En üstte, sayfadaki tüm yorumların tek cümlelik bir özetini görmeniz gerekir.
  5. Yeni bir yorum ekleyip sayfayı yenileyin. Özet değişikliği göreceksiniz.

11. Sonuç

Tebrikler! Bir 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