Node.js Admin SDK'sını kullanarak Firestore ile Cloud Run'a tam yığın Next.js uygulaması dağıtma

Node.js Admin SDK'sını kullanarak Firestore ile Cloud Run'a tam yığın Next.js uygulaması dağıtma

Bu codelab hakkında

subjectSon güncelleme Nis 11, 2025
account_circleYazan: Luke Schlangen

1. Genel Bakış

Cloud Run, kodunuzu doğrudan Google'ın ölçeklenebilir altyapısında çalıştırmanıza olanak tanıyan, tümüyle yönetilen bir platformdur. Bu Codelab'de, Cloud Run'daki bir Next.js uygulamasının Node.js Admin SDK'sı kullanılarak Firestore veritabanına nasıl bağlanacağı gösterilmektedir.

Bu laboratuvarda şunları öğreneceksiniz:

  • Firestore veritabanı oluşturma
  • Cloud Run'a, Firestore veritabanınıza bağlanan bir uygulama dağıtma

2. Ön koşullar

  1. Google Hesabınız yoksa Google Hesabı oluşturmanız gerekir.
    • İş veya okul hesabı yerine kişisel hesap kullanıyorsanız. İş ve okul hesaplarında, bu laboratuvar için gereken API'leri etkinleştirmenizi engelleyen kısıtlamalar olabilir.

3. Proje ayarlama

  1. Google Cloud Console'da oturum açın.
  2. Cloud Console'da faturalandırmayı etkinleştirin.
    • Bu laboratuvarı tamamlamak, bulut kaynaklarında 1 ABD dolarından az maliyete mal olur.
    • Daha fazla ödeme alınmaması için bu laboratuvarın sonundaki adımları uygulayarak kaynakları silebilirsiniz.
    • Yeni kullanıcılar 300 ABD doları tutarındaki ücretsiz deneme sürümünden yararlanabilir.
  3. Yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanmayı seçin.

4. Cloud Shell Düzenleyici'yi açma

  1. Cloud Shell Düzenleyici'ye gidin
  2. Terminal ekranın alt kısmında görünmüyorsa açın:
    • Hamburger menüsünü Hamburger menü simgesi tıklayın.
    • Terminal'i tıklayın.
    • Yeni Terminal'i tıklayınCloud Shell Düzenleyici'de yeni terminal açma
  3. Terminalde projenizi şu komutla ayarlayın:
    • Biçim:
      gcloud config set project [PROJECT_ID]
    • Örnek:
      gcloud config set project lab-project-id-example
    • Proje kimliğinizi hatırlamıyorsanız:
      • Tüm proje kimliklerinizi şu komutla listeleyebilirsiniz:
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
      Cloud Shell Düzenleyici terminalinde proje kimliğini ayarlama
  4. Yetkilendirme isteğinde bulunulursa devam etmek için Yetkilendir'i tıklayın. Cloud Shell'e yetki vermek için tıklayın
  5. Aşağıdaki mesajı görürsünüz:
    Updated property [core/project].
    
    WARNING görüyorsanız ve Do you want to continue (Y/N)? soruyorsanız proje kimliğini yanlış girdiğiniz muhtemeldir. N, Enter tuşlarına basın ve gcloud config set project komutunu tekrar çalıştırmayı deneyin.

5. API'leri etkinleştir

Terminalde API'leri etkinleştirin:

gcloud services enable \
  firestore.googleapis.com \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

Yetkilendirme isteğinde bulunulursa devam etmek için Yetkilendir'i tıklayın. Cloud Shell'e yetki vermek için tıklayın

Bu komutun tamamlanması birkaç dakika sürebilir ancak sonunda şuna benzer bir başarılı mesaj gösterilir:

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

6. Firestore veritabanı oluşturma

  1. Firestore veritabanı oluşturmak için gcloud firestore databases create komutunu çalıştırın
    gcloud firestore databases create --location=nam5

7. Başvuruyu hazırlama

HTTP isteklerine yanıt veren bir Next.js uygulaması hazırlayın.

  1. task-app adlı yeni bir Next.js projesi oluşturmak için şu komutu kullanın:
    npx --yes create-next-app@15.2.4 task-app \
      --ts \
      --eslint \
      --tailwind \
      --no-src-dir \
      --turbopack \
      --app \
      --no-import-alias
  2. Dizin task-app olarak değiştirilir:
    cd task-app
  1. Firestore veritabanı ile etkileşimde bulunmak için firebase-admin'ü yükleyin.
    npm install firebase-admin
  1. actions.ts dosyasını Cloud Shell Düzenleyici'de açın:
    cloudshell edit app/actions.ts
    Ekranın üst kısmında boş bir dosya görünür. Bu actions.ts dosyasını buradan düzenleyebilirsiniz. Kodun ekranın üst kısmına yerleştirildiğini gösterin
  2. Aşağıdaki kodu kopyalayıp açılan actions.ts dosyasına yapıştırın:
    'use server'
    import { initializeApp, applicationDefault, getApps } from 'firebase-admin/app';
    import { getFirestore } from 'firebase-admin/firestore';
    const credential = applicationDefault();

    // Only initialize app if it does not already exist
    if (getApps().length === 0) {
      initializeApp({ credential });
    }

    const db = getFirestore();
    const tasksRef = db.collection('tasks');

    type Task = {
      id: string;
      title: string;
      status: 'IN_PROGRESS' | 'COMPLETE';
      createdAt: number;
    };

    // CREATE
    export async function addNewTaskToDatabase(newTask: string) {
      await tasksRef.doc().create({
        title: newTask,
        status: 'IN_PROGRESS',
        createdAt: Date.now(),
      });
      return;
    }

    // READ
    export async function getTasksFromDatabase() {
      const snapshot = await tasksRef.orderBy('createdAt', 'desc').limit(100).get();
      const tasks = await snapshot.docs.map(doc => ({
        id: doc.id,
        title: doc.data().title,
        status: doc.data().status,
        createdAt: doc.data().createdAt,
      }));
      return tasks;
    }

    // UPDATE
    export async function updateTaskInDatabase(task: Task) {
      await tasksRef.doc(task.id).set(task);
      return;
    }

    // DELETE
    export async function deleteTaskFromDatabase(taskId: string) {
      await tasksRef.doc(taskId).delete();
      return;
    }
  1. page.tsx dosyasını Cloud Shell Düzenleyici'de açın:
    cloudshell edit app/page.tsx
    Ekranın üst kısmında mevcut bir dosya gösterilir. Bu page.tsx dosyasını buradan düzenleyebilirsiniz. Kodun ekranın üst kısmına yerleştirildiğini gösterin
  2. page.tsx dosyasının mevcut içeriğini silin.
  3. Aşağıdaki kodu kopyalayıp açılan page.tsx dosyasına yapıştırın:
    'use client'
    import React, { useEffect, useState } from "react";
    import { addNewTaskToDatabase, getTasksFromDatabase, deleteTaskFromDatabase, updateTaskInDatabase } from "./actions";

    type Task = {
      id: string;
      title: string;
      status: 'IN_PROGRESS' | 'COMPLETE';
      createdAt: number;
    };

    export default function Home() {
      const [newTaskTitle, setNewTaskTitle] = useState('');
      const [tasks, setTasks] = useState<Task[]>([]);

      async function getTasks() {
        const updatedListOfTasks = await getTasksFromDatabase();
        setTasks(updatedListOfTasks);
      }

      useEffect(() => {
        getTasks();
      }, []);

      async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
        e.preventDefault();
        await addNewTaskToDatabase(newTaskTitle);
        await getTasks();
        setNewTaskTitle('');
      };

      async function updateTask(task: Task, newTaskValues: Partial<Task>) {
        await updateTaskInDatabase({ ...task, ...newTaskValues });
        await getTasks();
      }

      async function deleteTask(taskId: string) {
        await deleteTaskFromDatabase(taskId);
        await getTasks();
      }

      return (
        <main className="p-4">
          <h2 className="text-2xl font-bold mb-4">To Do List</h2>
          <div className="flex mb-4">
            <form onSubmit={handleSubmit} className="flex mb-8">
              <input
                type="text"
                placeholder="New Task Title"
                value={newTaskTitle}
                onChange={(e) => setNewTaskTitle(e.target.value)}
                className="flex-grow border border-gray-400 rounded px-3 py-2 mr-2 bg-inherit"
              />
              <button
                type="submit"
                className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-nowrap"
              >
                Add New Task
              </button>
            </form>
          </div>
          <table className="w-full">
            <tbody>
              {tasks.map(function (task) {
                const isComplete = task.status === 'COMPLETE';
                return (
                  <tr key={task.id} className="border-b border-gray-200">
                    <td className="py-2 px-4">
                      <input
                        type="checkbox"
                        checked={isComplete}
                        onChange={() => updateTask(task, { status: isComplete ? 'IN_PROGRESS' : 'COMPLETE' })}
                        className="transition-transform duration-300 ease-in-out transform scale-100 checked:scale-125 checked:bg-green-500"
                      />
                    </td>
                    <td className="py-2 px-4">
                      <span
                        className={`transition-all duration-300 ease-in-out ${isComplete ? 'line-through text-gray-400 opacity-50' : 'opacity-100'}`}
                      >
                        {task.title}
                      </span>
                    </td>
                    <td className="py-2 px-4">
                      <button
                        onClick={() => deleteTask(task.id)}
                        className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded float-right"
                      >
                        Delete
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </main>
      );
    }

Uygulama artık dağıtılmaya hazırdır.

8. Uygulamayı Cloud Run&#39;a dağıtma

  1. Uygulamanızı Cloud Run'a dağıtmak için aşağıdaki komutu çalıştırın:
    gcloud run deploy helloworld \
      --region=us-central1 \
      --source=.
  2. İstenirse devam etmek istediğinizi onaylamak için Y ve Enter'ye basın:
    Do you want to continue (Y/n)? Y
    

Birkaç dakika sonra uygulama, ziyaret etmeniz için bir URL sağlar.

Uygulamanızı çalışırken görmek için URL'ye gidin. URL'yi her ziyaret ettiğinizde veya sayfayı her yenilediğinizde görev uygulamasını görürsünüz.

9. Tebrikler

Bu laboratuvarda şunları nasıl yapacağınızı öğrendiniz:

  • PostgreSQL için Cloud SQL örneği oluşturma
  • Cloud Run'a, Cloud SQL veritabanınıza bağlanan bir uygulama dağıtma

Temizleme

Cloud SQL'in ücretsiz katmanı yoktur ve kullanmaya devam ederseniz sizden ücret alınır. Ek ücret ödememek için Cloud projenizi silebilirsiniz.

Cloud Run, hizmet kullanılmadığında ücret almaz ancak container görüntüsünü Artifact Registry'de depolamak için sizden ücret alınabilir. Cloud projeniz silindiğinde, söz konusu projede kullanılan tüm kaynakların faturalandırması durdurulur.

İsterseniz projeyi silin:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

Gereksiz kaynakları CloudShell diskinizden de silebilirsiniz. Şunları yapabilirsiniz:

  1. Codelab proje dizinini silin:
    rm -rf ~/task-app
  2. Uyarı! Sonraki işlem geri alınamaz. Yer açmak için Cloud Shell'inizdeki her şeyi silmek istiyorsanız ana dizininizi tamamen silebilirsiniz. Saklamak istediğiniz her şeyin başka bir yere kaydedildiğinden emin olun.
    sudo rm -rf $HOME

Öğrenmeye devam edin