ผสานรวม Firebase กับแอป Next.js

1. ก่อนเริ่มต้น

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีผสานรวม Firebase กับเว็บแอป Next.js ที่ชื่อ Friendly Eats ซึ่งเป็นเว็บไซต์สำหรับรีวิวร้านอาหาร

เว็บแอป Friendly Eats

เว็บแอปที่สร้างเสร็จแล้วมีฟีเจอร์ที่มีประโยชน์ซึ่งแสดงให้เห็นว่า Firebase ช่วยคุณสร้างแอป Next.js ได้อย่างไร ฟีเจอร์เหล่านี้ ได้แก่

  • สร้างและติดตั้งใช้งานโดยอัตโนมัติ: Codelab นี้ใช้ Firebase App Hosting เพื่อสร้างและติดตั้งใช้งานโค้ด Next.js โดยอัตโนมัติทุกครั้งที่คุณพุชไปยังกิ่งที่กำหนดค่าไว้
  • การลงชื่อเข้าใช้และออกจากระบบ: เว็บแอปที่เสร็จสมบูรณ์แล้วจะช่วยให้คุณลงชื่อเข้าใช้ด้วย Google และออกจากระบบได้ ระบบจะจัดการการเข้าสู่ระบบและการคงอยู่ของผู้ใช้ผ่าน Firebase Authentication ทั้งหมด
  • รูปภาพ: เว็บแอปที่เสร็จสมบูรณ์แล้วจะช่วยให้ผู้ใช้ที่ลงชื่อเข้าใช้สามารถอัปโหลดรูปภาพร้านอาหารได้ ระบบจะจัดเก็บชิ้นงานรูปภาพไว้ใน Cloud Storage for Firebase Firebase JavaScript SDK มี URL สาธารณะสำหรับรูปภาพที่อัปโหลด จากนั้นระบบจะจัดเก็บ URL สาธารณะนี้ไว้ในเอกสารร้านอาหารที่เกี่ยวข้องใน Cloud Firestore
  • รีวิว: เว็บแอปที่เสร็จสมบูรณ์แล้วจะช่วยให้ผู้ใช้ที่ลงชื่อเข้าใช้โพสต์รีวิวร้านอาหารซึ่งประกอบด้วยการให้คะแนนเป็นดาวและข้อความที่เป็นข้อความได้ ระบบจะจัดเก็บข้อมูลรีวิวไว้ใน Cloud Firestore
  • ตัวกรอง: เว็บแอปที่เสร็จสมบูรณ์แล้วจะช่วยให้ผู้ใช้ที่ลงชื่อเข้าใช้กรองรายชื่อร้านอาหารตามหมวดหมู่ สถานที่ตั้ง และราคาได้ นอกจากนี้ คุณยังปรับแต่งวิธีการจัดเรียงที่ใช้ได้ด้วย ระบบจะเข้าถึงข้อมูลจาก Cloud Firestore และใช้การค้นหา Firestore ตามตัวกรองที่ใช้

ข้อกำหนดเบื้องต้น

  • บัญชี GitHub
  • ความรู้เกี่ยวกับ Next.js และ JavaScript

สิ่งที่คุณจะได้เรียนรู้

  • วิธีใช้ Firebase กับ App Router ของ Next.js และการแสดงผลฝั่งเซิร์ฟเวอร์
  • วิธีจัดเก็บรูปภาพอย่างถาวรใน Cloud Storage for Firebase
  • วิธีอ่านและเขียนข้อมูลในฐานข้อมูล Cloud Firestore
  • วิธีใช้ Sign in with Google กับ Firebase JavaScript SDK

สิ่งที่ต้องมี

  • Git
  • Node.js เวอร์ชันเสถียรล่าสุด
  • เบราว์เซอร์ที่คุณเลือก เช่น Google Chrome
  • สภาพแวดล้อมในการพัฒนาที่มีเครื่องมือแก้ไขโค้ดและเทอร์มินัล
  • บัญชี Google สำหรับการสร้างและการจัดการโปรเจ็กต์ Firebase
  • ความสามารถในการอัปเกรดโปรเจ็กต์ Firebase เป็นแพ็กเกจราคา Blaze

2. ตั้งค่าสภาพแวดล้อมในการพัฒนาและที่เก็บ GitHub

Codelab นี้มีโค้ดเบสเริ่มต้นของแอปและใช้ Firebase CLI

สร้างที่เก็บ GitHub

คุณดูแหล่งที่มาของ Codelab ได้ที่ https://github.com/firebase/friendlyeats-web ที่เก็บมีโปรเจ็กต์ตัวอย่างสำหรับหลายแพลตฟอร์ม อย่างไรก็ตาม Codelab นี้ใช้เฉพาะไดเรกทอรี nextjs-start โปรดทราบไดเรกทอรีต่อไปนี้

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

คัดลอกโฟลเดอร์ nextjs-start ไปยังที่เก็บของคุณเอง

  1. ใช้เทอร์มินัลเพื่อสร้างโฟลเดอร์ใหม่ในคอมพิวเตอร์และเปลี่ยนเป็นไดเรกทอรีใหม่โดยทำดังนี้
    mkdir codelab-friendlyeats-web
    
    cd codelab-friendlyeats-web
    
  2. ใช้แพ็กเกจ npm giget เพื่อดึงเฉพาะโฟลเดอร์ nextjs-start
    npx giget@latest "gh:firebase/friendlyeats-web/nextjs-start#master" . --install
    
  3. ติดตามการเปลี่ยนแปลงในเครื่องด้วย Git
    git init
    
    git add .
    
    git commit -m "Codelab starting point"
    
    git branch -M main
    
  4. สร้างที่เก็บ GitHub ใหม่: https://github.com/new ตั้งชื่อได้ตามต้องการ
  5. คัดลอก URL ใหม่ที่ GitHub สร้างให้คุณ
  6. พุชการเปลี่ยนแปลงในเครื่องไปยังที่เก็บ GitHub ใหม่โดยเรียกใช้คำสั่งต่อไปนี้ แทนที่ตัวยึดตำแหน่ง <REPOSITORY_URL> ด้วย URL ของที่เก็บจริง
    git remote add origin <REPOSITORY_URL>
    
    git push -u origin main
    
  7. ตอนนี้คุณควรเห็นโค้ดเริ่มต้นในที่เก็บ GitHub แล้ว

ติดตั้งหรืออัปเดต Firebase CLI

เรียกใช้คำสั่งต่อไปนี้เพื่อยืนยันว่าคุณได้ติดตั้ง Firebase CLI และเป็นเวอร์ชัน 14.1.0 ขึ้นไป

firebase --version

หากเห็นเวอร์ชันที่ต่ำกว่าหรือไม่ได้ติดตั้ง Firebase CLI ให้เรียกใช้คำสั่งติดตั้ง

npm install -g firebase-tools@latest

หากติดตั้ง Firebase CLI ไม่ได้เนื่องจากข้อผิดพลาดเกี่ยวกับสิทธิ์ โปรดดูเอกสารประกอบของ npm หรือใช้ตัวเลือกการติดตั้งอื่น

เข้าสู่ระบบ Firebase

  1. เรียกใช้คำสั่งต่อไปนี้เพื่อเข้าสู่ระบบ Firebase CLI
    firebase login
    
  2. ป้อน Y หรือ N ขึ้นอยู่กับว่าคุณต้องการให้ Firebase รวบรวมข้อมูลหรือไม่
  3. ในเบราว์เซอร์ ให้เลือกบัญชี Google แล้วคลิกอนุญาต

3. ตั้งค่าโปรเจ็กต์ Firebase

ในส่วนนี้ คุณจะตั้งค่าโปรเจ็กต์ Firebase และเชื่อมโยงเว็บแอป Firebase กับโปรเจ็กต์ นอกจากนี้ คุณยังต้องตั้งค่าบริการ Firebase ที่เว็บแอปตัวอย่างใช้ด้วย

สร้างโปรเจ็กต์ Firebase

  1. ลงชื่อเข้าใช้คอนโซล Firebase โดยใช้บัญชี Google เดียวกับที่คุณใช้ในขั้นตอนก่อนหน้า
  2. คลิกปุ่มเพื่อสร้างโปรเจ็กต์ใหม่ แล้วป้อนชื่อโปรเจ็กต์ (เช่น FriendlyEats Codelab)
  3. คลิกต่อไป
  4. หากได้รับแจ้ง ให้อ่านและยอมรับข้อกำหนดของ Firebase แล้วคลิกต่อไป
  5. (ไม่บังคับ) เปิดใช้ความช่วยเหลือจาก AI ในคอนโซล Firebase (เรียกว่า "Gemini ใน Firebase")
  6. สำหรับ Codelab นี้ คุณไม่จำเป็นต้องใช้ Google Analytics ดังนั้นให้ปิดตัวเลือก Google Analytics
  7. คลิกสร้างโปรเจ็กต์ รอให้ระบบจัดสรรโปรเจ็กต์ แล้วคลิกดำเนินการต่อ

อัปเกรดแพ็กเกจราคาของ Firebase

หากต้องการใช้ Firebase App Hosting และ Cloud Storage สำหรับ Firebase โปรเจ็กต์ Firebase ของคุณต้องอยู่ในแพ็กเกจราคาแบบจ่ายเมื่อใช้ (Blaze) ซึ่งหมายความว่าต้องลิงก์กับบัญชีการเรียกเก็บเงินในระบบคลาวด์

หากต้องการอัปเกรดโปรเจ็กต์เป็นแพ็กเกจ Blaze ให้ทำตามขั้นตอนต่อไปนี้

  1. ในคอนโซล Firebase ให้เลือกอัปเกรดแพ็กเกจ
  2. เลือกแพ็กเกจ Blaze ทำตามวิธีการบนหน้าจอเพื่อลิงก์บัญชีสำหรับการเรียกเก็บเงินใน Cloud กับโปรเจ็กต์
    หากคุณต้องสร้างบัญชีสำหรับการเรียกเก็บเงินใน Cloud เป็นส่วนหนึ่งของการอัปเกรดนี้ คุณอาจต้องกลับไปที่ขั้นตอนการอัปเกรดใน Firebase Console เพื่อทำการอัปเกรดให้เสร็จสมบูรณ์

เพิ่มเว็บแอปไปยังโปรเจ็กต์ Firebase

  1. ไปที่ภาพรวมโปรเจ็กต์ในโปรเจ็กต์ Firebase คลิกเพิ่มแอป แล้วคลิกเว็บ
  2. ในกล่องข้อความชื่อเล่นของแอป ให้ป้อนชื่อเล่นของแอปที่จำง่าย เช่น My Next.js app
  3. ไม่ต้องเลือกช่องทำเครื่องหมายตั้งค่าโฮสติ้งของ Firebase สำหรับแอปนี้ด้วย
  4. คลิกลงทะเบียนแอป > ไปที่คอนโซล

ตั้งค่าบริการ Firebase ในคอนโซล Firebase

ตั้งค่าการตรวจสอบสิทธิ์

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือกการตรวจสอบสิทธิ์
  2. คลิกเริ่มต้นใช้งาน
  3. ในคอลัมน์ผู้ให้บริการลงชื่อเข้าใช้ ให้คลิก Google > เปิดใช้
  4. ในกล่องข้อความชื่อที่เปิดเผยต่อสาธารณะสำหรับโปรเจ็กต์ ให้ป้อนชื่อที่จดจำง่าย เช่น My Next.js app
  5. เลือกอีเมลของคุณจากเมนูแบบเลื่อนลงอีเมลสนับสนุนสำหรับโปรเจ็กต์
  6. คลิกบันทึก

ตั้งค่า Cloud Firestore

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือกฐานข้อมูล Firestore
  2. คลิกสร้างฐานข้อมูล
  3. เลือกรุ่นมาตรฐาน แล้วคลิกถัดไป
  4. อย่าเปลี่ยนรหัสฐานข้อมูล ให้ตั้งค่าเป็น (default)
  5. เลือกตำแหน่งสำหรับฐานข้อมูล แล้วคลิกถัดไป
    สำหรับแอปจริง คุณควรเลือกตำแหน่งที่อยู่ใกล้กับผู้ใช้
  6. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย
    ในภายหลังใน Codelab นี้ คุณจะเพิ่มกฎความปลอดภัยเพื่อรักษาความปลอดภัยของข้อมูล อย่าเผยแพร่หรือเปิดเผยแอปต่อสาธารณะโดยไม่ได้เพิ่มกฎความปลอดภัยสำหรับฐานข้อมูล
  7. คลิกสร้าง

ตั้งค่า Cloud Storage for Firebase

  1. ในแผงด้านซ้ายของคอนโซล Firebase ให้ขยายสร้าง แล้วเลือก Storage
  2. คลิกเริ่มต้นใช้งาน
  3. เลือกตำแหน่งสำหรับที่เก็บข้อมูลเริ่มต้น
    ที่เก็บข้อมูลใน US-WEST1, US-CENTRAL1 และ US-EAST1 จะใช้ประโยชน์จากระดับ"ใช้งานฟรีเสมอ" สำหรับ Google Cloud Storage ได้ ที่เก็บข้อมูลในตำแหน่งอื่นๆ ทั้งหมดจะเป็นไปตามราคาและการใช้งาน Google Cloud Storage
  4. คลิกเริ่มในโหมดทดสอบ อ่านข้อจำกัดความรับผิดเกี่ยวกับกฎความปลอดภัย
    ในภายหลังใน Codelab นี้ คุณจะเพิ่มกฎความปลอดภัยเพื่อรักษาความปลอดภัยของข้อมูล อย่าเผยแพร่หรือแสดงแอปต่อสาธารณะโดยไม่ได้เพิ่มกฎความปลอดภัยสำหรับที่เก็บข้อมูล
  5. คลิกสร้าง

ติดตั้งใช้งานกฎความปลอดภัย

โค้ดมีชุดกฎการรักษาความปลอดภัยสำหรับ Firestore และสำหรับ Cloud Storage สำหรับ Firebase อยู่แล้ว หลังจากที่คุณติดตั้งใช้งานกฎความปลอดภัยแล้ว ข้อมูลในฐานข้อมูลและที่เก็บข้อมูลจะได้รับการปกป้องจากการละเมิดได้ดียิ่งขึ้น

  1. ในเทอร์มินัล ให้กำหนดค่า CLI เพื่อใช้โปรเจ็กต์ Firebase ที่คุณสร้างไว้ก่อนหน้านี้โดยทำดังนี้
    firebase use --add
    
    เมื่อได้รับข้อความแจ้งให้ระบุชื่อแทน ให้ป้อน friendlyeats-codelab
  2. หากต้องการติดตั้งใช้งานกฎความปลอดภัยเหล่านี้ (รวมถึงดัชนีที่จะต้องใช้ในภายหลัง) ให้เรียกใช้คำสั่งนี้ในเทอร์มินัล
    firebase deploy --only firestore,storage
    
  3. หากระบบถามว่า "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" ให้กด Enter เพื่อเลือกใช่

4. ตรวจสอบโค้ดเบสเริ่มต้น

ในส่วนนี้ คุณจะได้ตรวจสอบโค้ดเบสเริ่มต้นของแอปบางส่วน ซึ่งคุณจะเพิ่มฟังก์ชันการทำงานในโค้ดแล็บนี้

โครงสร้างโฟลเดอร์และไฟล์

ตารางต่อไปนี้แสดงภาพรวมของโครงสร้างโฟลเดอร์และไฟล์ของแอป

โฟลเดอร์และไฟล์

คำอธิบาย

src/components

คอมโพเนนต์ React สำหรับตัวกรอง ส่วนหัว รายละเอียดร้านอาหาร และรีวิว

src/lib

ฟังก์ชันยูทิลิตีที่ไม่จำเป็นต้องเชื่อมโยงกับ React หรือ Next.js

src/lib/firebase

โค้ดและการกำหนดค่า Firebase โดยเฉพาะ

public

ชิ้นงานแบบคงที่ในเว็บแอป เช่น ไอคอน

src/app

การกำหนดเส้นทางด้วย App Router ของ Next.js

package.json และ package-lock.json

ทรัพยากร Dependency ของโปรเจ็กต์ด้วย npm

next.config.js

การกำหนดค่าเฉพาะ Next.js (เปิดใช้การดำเนินการของเซิร์ฟเวอร์)

jsconfig.json

การกำหนดค่าบริการภาษา JavaScript

คอมโพเนนต์ฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์

แอปนี้เป็นเว็บแอป Next.js ที่ใช้App Router การแสดงผลฝั่งเซิร์ฟเวอร์ใช้ทั่วทั้งแอป ตัวอย่างเช่น ไฟล์ src/app/page.js เป็นคอมโพเนนต์ฝั่งเซิร์ฟเวอร์ที่รับผิดชอบหน้าหลัก src/components/RestaurantListings.jsx เป็นคอมโพเนนต์ไคลเอ็นต์ที่ระบุโดยคำสั่ง "use client" ที่จุดเริ่มต้นของไฟล์

นำเข้าใบแจ้งยอด

คุณอาจเห็นคำสั่งนำเข้าดังต่อไปนี้

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

แอปใช้สัญลักษณ์ @ เพื่อหลีกเลี่ยงเส้นทางการนำเข้าแบบสัมพัทธ์ที่ซับซ้อน และใช้นามแฝงของเส้นทาง

API เฉพาะของ Firebase

โค้ด Firebase API ทั้งหมดจะอยู่ในไดเรกทอรี src/lib/firebase จากนั้นคอมโพเนนต์ React แต่ละรายการจะนำเข้าฟังก์ชันที่ห่อไว้จากไดเรกทอรี src/lib/firebase แทนที่จะนำเข้าฟังก์ชัน Firebase โดยตรง

ข้อมูลจำลอง

ข้อมูลร้านอาหารและรีวิวจำลองจะอยู่ในไฟล์ src/lib/randomData.js ระบบจะรวบรวมข้อมูลจากไฟล์นั้นไว้ในโค้ดในไฟล์ src/lib/fakeRestaurants.js

5. สร้างแบ็กเอนด์ App Hosting

ในส่วนนี้ คุณจะตั้งค่าแบ็กเอนด์ App Hosting เพื่อดูสาขาในที่เก็บ Git

เมื่อสิ้นสุดส่วนนี้ คุณจะมีแบ็กเอนด์การโฮสต์แอปที่เชื่อมต่อกับที่เก็บใน GitHub ซึ่งจะสร้างใหม่และเปิดตัวแอปเวอร์ชันใหม่โดยอัตโนมัติทุกครั้งที่คุณพุชคอมมิตใหม่ไปยังสาขา main

สร้างแบ็กเอนด์

  1. ไปที่หน้าApp Hosting ในคอนโซล Firebase
  2. คลิกเริ่มต้นใช้งานเพื่อเริ่มขั้นตอนการสร้างแบ็กเอนด์
  3. เลือกภูมิภาค สำหรับแอปจริง คุณควรเลือกภูมิภาคที่ใกล้กับผู้ใช้มากที่สุด
  4. ทำตามข้อความแจ้งในขั้นตอนนำเข้าที่เก็บ GitHub เพื่อตั้งค่าการตรวจสอบสิทธิ์ GitHub
  5. จากที่เก็บ ให้เลือกให้สิทธิ์เข้าถึงที่เก็บใหม่ใน GitHub แล้วทำตามข้อความแจ้งเพื่อเปิดใช้สิทธิ์เข้าถึงที่เก็บ GitHub ที่คุณสร้างไว้ก่อนหน้านี้
  6. คลิกรีเฟรชรายการเพื่อรีเฟรชรายการ จากนั้นเลือกที่เก็บและคลิกถัดไป
  7. ตั้งค่าการทำให้ใช้งานได้
    1. ตั้งค่าสาขาที่ใช้งานจริงเป็น main
    2. เก็บไดเรกทอรีรากไว้เป็น /
    3. เปิดใช้การเปิดตัวอัตโนมัติ
  8. ตั้งชื่อแบ็กเอนด์ friendlyeats-codelab แล้วคลิกถัดไป
  9. จากเชื่อมโยงเว็บแอป Firebase ให้เลือกเลือกเว็บแอป Firebase ที่มีอยู่ แล้วเลือกแอปที่คุณเพิ่มจากรายการ
  10. คลิกเสร็จสิ้นและนำไปใช้ ระบบจะเปลี่ยนเส้นทางคุณไปยังหน้าใหม่ ซึ่งคุณจะเห็นสถานะของแบ็กเอนด์การโฮสต์แอปใหม่
  11. คลิกดูเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับการติดตั้งใช้งาน App Hosting รวมถึงสถานะการเปิดตัว บันทึก และรายละเอียดการใช้งาน
  12. หลังจากเปิดตัวเสร็จแล้ว ให้คลิกเพื่อเปิด URL ของเว็บไซต์ในส่วนโดเมน การดำเนินการนี้อาจใช้เวลาสักครู่จึงจะเริ่มทำงานเนื่องจากการเผยแพร่ DNS
  13. อ๊ะ! เมื่อโหลดหน้าเว็บ คุณจะเห็นข้อความแสดงข้อผิดพลาดที่ระบุว่า "ข้อผิดพลาดของแอปพลิเคชัน: เกิดข้อยกเว้นฝั่งเซิร์ฟเวอร์ (ดูข้อมูลเพิ่มเติมได้ในบันทึกของเซิร์ฟเวอร์)"
  14. ในคอนโซล Firebase ให้ตรวจสอบแท็บบันทึกของแบ็กเอนด์ App Hosting คุณจะเห็นบันทึก "ข้อผิดพลาด: ไม่ได้ติดตั้งใช้งาน" เราจะแก้ไขปัญหานี้ในขั้นตอนถัดไปเมื่อเพิ่มการตรวจสอบสิทธิ์

คุณได้ติดตั้งใช้งานเว็บแอปเริ่มต้นแล้ว ทุกครั้งที่คุณพุชคอมมิตใหม่ไปยังกิ่ง main ของที่เก็บ GitHub คุณจะเห็นว่าการบิลด์และการเปิดตัวใหม่เริ่มขึ้นในคอนโซล Firebase และเว็บไซต์จะอัปเดตโดยอัตโนมัติหลังจากที่การเปิดตัวเสร็จสมบูรณ์

6. เพิ่มการตรวจสอบสิทธิ์ลงในเว็บแอป

ในส่วนนี้ คุณจะเพิ่มการตรวจสอบสิทธิ์ลงในเว็บแอปเพื่อให้เข้าสู่ระบบได้

เพิ่มโดเมนที่ได้รับอนุญาต

การตรวจสอบสิทธิ์ Firebase จะยอมรับเฉพาะคำขอลงชื่อเข้าใช้จากโดเมนที่คุณอนุญาตเท่านั้น ในส่วนนี้ เราจะเพิ่มโดเมนของแบ็กเอนด์การโฮสต์แอปไปยังรายการโดเมนที่ได้รับอนุมัติในโปรเจ็กต์

  1. เปิดหน้าการโฮสต์แอป แล้วคลิกดูใต้เว็บไซต์ที่ติดตั้งใช้งานเพื่อเข้าถึงหน้าภาพรวม คัดลอกชื่อโดเมนของแบ็กเอนด์ App Hosting
  2. ไปที่แท็บการตั้งค่าการตรวจสอบสิทธิ์ แล้วเลือกโปรเจ็กต์ที่ต้องการเพิ่มโดเมนที่ได้รับอนุญาต จากนั้นค้นหาส่วนโดเมนที่ได้รับอนุญาต แล้วคลิก
  3. คลิกปุ่มเพิ่มโดเมน
  4. ป้อนโดเมนของแบ็กเอนด์ App Hosting
  5. คลิกเพิ่ม

ใช้ฟังก์ชันการลงชื่อเข้าใช้และออกจากระบบ

ในไฟล์ src/lib/firebase/auth.js ให้แทนที่ฟังก์ชัน onAuthStateChanged, onIdTokenChanged, signInWithGoogle และ signOut ด้วยโค้ดต่อไปนี้

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

โค้ดนี้ใช้ Firebase API ต่อไปนี้

Firebase API

คำอธิบาย

auth.onAuthStateChanged

เพิ่ม Observer สำหรับการเปลี่ยนแปลงสถานะการลงชื่อเข้าใช้ของผู้ใช้

auth.onIdTokenChanged

เพิ่ม Observer สำหรับการเปลี่ยนแปลงโทเค็นรหัสของผู้ใช้

GoogleAuthProvider

สร้างอินสแตนซ์ของผู้ให้บริการการตรวจสอบสิทธิ์ของ Google

signInWithPopup

เริ่มขั้นตอนการตรวจสอบสิทธิ์ที่อิงตามกล่องโต้ตอบ

auth.signOut

นำผู้ใช้ออกจากระบบ

ในไฟล์ src/components/Header.jsx โค้ดจะเรียกใช้ฟังก์ชัน signInWithGoogle และ signOut อยู่แล้ว

ส่งสถานะการตรวจสอบสิทธิ์ไปยังเซิร์ฟเวอร์

เราจะใช้คุกกี้เพื่อส่งสถานะการตรวจสอบสิทธิ์ไปยังเซิร์ฟเวอร์ เมื่อใดก็ตามที่สถานะการตรวจสอบสิทธิ์เปลี่ยนแปลงในไคลเอ็นต์ เราจะอัปเดตคุกกี้ __session

ใน src/components/Header.jsx ให้แทนที่ฟังก์ชัน useUserSession ด้วยโค้ดต่อไปนี้

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

อ่านสถานะการตรวจสอบสิทธิ์ในเซิร์ฟเวอร์

เราจะใช้ FirebaseServerApp เพื่อจำลองสถานะการตรวจสอบสิทธิ์ของไคลเอ็นต์ในเซิร์ฟเวอร์

เปิด src/lib/firebase/serverApp.js แล้วแทนที่ฟังก์ชัน getAuthenticatedAppForUser โดยทำดังนี้

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

ยืนยันการเปลี่ยนแปลง

เลย์เอาต์รูทในไฟล์ src/app/layout.js จะแสดงผลส่วนหัวและส่งผู้ใช้เป็นพร็อพ (หากมี)

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

ซึ่งหมายความว่าคอมโพเนนต์ <Header> จะแสดงข้อมูลผู้ใช้ (หากมี) ในระหว่างรันไทม์ของเซิร์ฟเวอร์ หากมีการอัปเดตการตรวจสอบสิทธิ์ในระหว่างวงจรของหน้าเว็บหลังจากโหลดหน้าเว็บครั้งแรก onAuthStateChanged จะจัดการการอัปเดตเหล่านั้น

ตอนนี้ได้เวลาเปิดตัวบิลด์ใหม่และยืนยันสิ่งที่คุณสร้างแล้ว

  1. สร้างคอมมิตที่มีข้อความคอมมิตว่า "เพิ่มการตรวจสอบสิทธิ์" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Add authentication"
    
    git push
    
  2. เปิดหน้าการโฮสต์แอป แล้วคลิก URL ของเว็บไซต์เพื่อเปิดเมื่อการเปิดตัวใหม่เสร็จสมบูรณ์
  3. ทดสอบการตรวจสอบสิทธิ์
    1. ลงชื่อเข้าใช้ด้วยบัญชี Google และตรวจสอบว่าชื่อที่แสดงปรากฏในส่วนหัวหลังจากลงชื่อเข้าใช้
    2. ออกจากระบบแล้วลงชื่อเข้าใช้อีกครั้ง คุณทำขั้นตอนนี้ซ้ำกับผู้ใช้รายอื่นได้
    3. ไม่บังคับ: คลิกขวาที่เว็บแอป เลือกดูซอร์สโค้ดของหน้าเว็บ แล้วค้นหาชื่อที่แสดง โดยจะปรากฏในแหล่งที่มาของ HTML ดิบที่ส่งคืนจากเซิร์ฟเวอร์

7. ดูข้อมูลร้านอาหาร

เว็บแอปมีข้อมูลจำลองสำหรับร้านอาหารและรีวิว

เพิ่มร้านอาหารอย่างน้อย 1 ร้าน

หากต้องการแทรกข้อมูลร้านอาหารจำลองลงในฐานข้อมูล Cloud Firestore ในเครื่อง ให้ทำตามขั้นตอนต่อไปนี้

  1. ลงชื่อเข้าใช้เว็บแอป หากยังไม่ได้ทำ จากนั้นเลือก 2cf67d488d8e6332.png> เพิ่มร้านอาหารตัวอย่าง โปรดทราบว่าเราไม่เห็นร้านอาหารแสดงในเว็บแอป Friendly Eats เนื่องจากเรายังไม่ได้ตั้งค่าโค้ดการดึงข้อมูล เราจะแก้ไขปัญหานี้ในขั้นตอนถัดไป
  2. ในคอนโซล Firebase ในหน้าฐานข้อมูล Firestore ให้เลือก restaurants คุณจะเห็นเอกสารระดับบนสุดในคอลเล็กชันร้านอาหาร ซึ่งแต่ละเอกสารแสดงถึงร้านอาหาร
  3. คลิกเอกสาร 2-3 รายการเพื่อสำรวจพร็อพเพอร์ตี้ของเอกสารร้านอาหาร

แสดงรายชื่อร้านอาหาร

ตอนนี้ฐานข้อมูล Cloud Firestore มีร้านอาหารที่เว็บแอป Next.js แสดงได้แล้ว

หากต้องการกำหนดโค้ดการดึงข้อมูล ให้ทำตามขั้นตอนต่อไปนี้

  1. ในไฟล์ src/app/page.js ให้ค้นหาคอมโพเนนต์เซิร์ฟเวอร์ <Home /> แล้วตรวจสอบการเรียกใช้ฟังก์ชัน getRestaurants ซึ่งจะดึงรายการร้านอาหารในเวลาที่เซิร์ฟเวอร์ทำงาน คุณใช้ฟังก์ชัน getRestaurants ได้โดยทำตามขั้นตอนต่อไปนี้
  2. ในไฟล์ src/lib/firebase/firestore.js ให้แทนที่ฟังก์ชัน applyQueryFilters และ getRestaurants ด้วยโค้ดต่อไปนี้
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" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Read the list of restaurants from Firestore"
    
    git push
    
  2. เปิดหน้า App Hosting ในคอนโซล Firebase แล้วรอให้การเปิดตัวใหม่เสร็จสมบูรณ์
  3. ในเว็บแอป ให้รีเฟรชหน้า รูปภาพร้านอาหารจะปรากฏเป็นไทล์ในหน้า

ตรวจสอบว่าข้อมูลร้านอาหารโหลดที่รันไทม์ของเซิร์ฟเวอร์

การใช้เฟรมเวิร์ก Next.js อาจไม่ชัดเจนเมื่อมีการโหลดข้อมูลในเวลาเรียกใช้เซิร์ฟเวอร์หรือเวลาเรียกใช้ฝั่งไคลเอ็นต์

หากต้องการยืนยันว่าข้อมูลร้านอาหารโหลดที่รันไทม์ของเซิร์ฟเวอร์ ให้ทำตามขั้นตอนต่อไปนี้

  1. ในเว็บแอป ให้เปิด DevTools แล้วปิดใช้ JavaScript

ปิดใช้ JavaScript ในเครื่องมือสำหรับนักพัฒนาเว็บ

  1. รีเฟรชเว็บแอป ข้อมูลร้านอาหารจะยังคงโหลดอยู่ ข้อมูลร้านอาหารจะแสดงในการตอบกลับของเซิร์ฟเวอร์ เมื่อเปิดใช้ JavaScript ระบบจะ เติมข้อมูลร้านอาหารผ่านโค้ด JavaScript ฝั่งไคลเอ็นต์
  2. เปิดใช้ JavaScript อีกครั้งในเครื่องมือสำหรับนักพัฒนาเว็บ

ฟังการอัปเดตร้านอาหารด้วยเครื่องมือฟังสแนปชอตของ Cloud Firestore

ในส่วนก่อนหน้า คุณได้เห็นวิธีโหลดชุดร้านอาหารเริ่มต้นจากไฟล์ src/app/page.js ไฟล์ src/app/page.js เป็นคอมโพเนนต์ฝั่งเซิร์ฟเวอร์และแสดงผลบนเซิร์ฟเวอร์ ซึ่งรวมถึงโค้ดการดึงข้อมูล Firebase

ไฟล์ src/components/RestaurantListings.jsx เป็นคอมโพเนนต์ฝั่งไคลเอ็นต์และกำหนดค่าให้ไฮเดรตมาร์กอัปที่ฝั่งเซิร์ฟเวอร์ได้

หากต้องการกำหนดค่าไฟล์ src/components/RestaurantListings.jsx เพื่อไฮเดรตมาร์กอัปที่ฝั่งเซิร์ฟเวอร์ ให้ทำตามขั้นตอนต่อไปนี้

  1. ในไฟล์ src/components/RestaurantListings.jsx ให้สังเกตโค้ดต่อไปนี้ ซึ่งเขียนไว้ให้คุณแล้ว
useEffect(() => {
    return getRestaurantsSnapshot((data) => {
      setRestaurants(data);
    }, filters);
  }, [filters]);

โค้ดนี้จะเรียกใช้ฟังก์ชัน getRestaurantsSnapshot() ซึ่งคล้ายกับฟังก์ชัน getRestaurants() ที่คุณใช้ในขั้นตอนก่อนหน้า อย่างไรก็ตาม ฟังก์ชันสแนปชอตนี้มีกลไกการเรียกกลับเพื่อให้ระบบเรียกใช้การเรียกกลับทุกครั้งที่มีการเปลี่ยนแปลงคอลเล็กชันของร้านอาหาร

  1. ในไฟล์ src/lib/firebase/firestore.js ให้แทนที่ฟังก์ชัน getRestaurantsSnapshot() ด้วยโค้ดต่อไปนี้
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);
  });
}
  1. ในไฟล์ src/lib/firebase/firestore.js ให้แทนที่ฟังก์ชัน getRestaurantSnapshotById() ด้วยโค้ดต่อไปนี้
export function getRestaurantSnapshotById(restaurantId, cb) {
  if (!restaurantId) {
    console.log("Error: Invalid ID received: ", restaurantId);
    return;
  }

  if (typeof cb !== "function") {
    console.log("Error: The callback parameter is not a function");
    return;
  }

  const docRef = doc(db, "restaurants", restaurantId);
  return onSnapshot(docRef, (docSnap) => {
    cb({
      ...docSnap.data(),
      timestamp: docSnap.data().timestamp.toDate(),
    });
  });
}

การเปลี่ยนแปลงที่ทำผ่านหน้าฐานข้อมูล Firestore จะแสดงในเว็บแอปแบบเรียลไทม์แล้ว

  1. สร้างคอมมิตด้วยข้อความคอมมิต "Listen for realtime restaurant updates" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Listen for realtime restaurant updates"
    
    git push
    
  2. เปิดหน้า App Hosting ในคอนโซล Firebase แล้วรอให้การเปิดตัวใหม่เสร็จสมบูรณ์
  3. ในเว็บแอป ให้เลือก 27ca5d1e8ed8adfe.png> เพิ่มร้านอาหารตัวอย่าง หากคุณติดตั้งฟังก์ชันสแนปชอตอย่างถูกต้อง ร้านอาหารจะปรากฏแบบเรียลไทม์โดยไม่ต้องรีเฟรชหน้าเว็บ

8. บันทึกรีวิวที่ผู้ใช้ส่งจากเว็บแอป

  1. ในไฟล์ src/lib/firebase/firestore.js ให้แทนที่ฟังก์ชัน updateWithRating() ด้วยโค้ดต่อไปนี้
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()),
  });
};

โค้ดนี้จะแทรกเอกสาร Firestore ใหม่ซึ่งแสดงรีวิวใหม่ โค้ดยังอัปเดตเอกสาร Firestore ที่มีอยู่ซึ่งแสดงถึงร้านอาหารด้วยตัวเลขที่อัปเดตสำหรับจำนวนการให้คะแนนและการให้คะแนนเฉลี่ยที่คำนวณแล้ว

  1. แทนที่ฟังก์ชัน addReviewToRestaurant() ด้วยโค้ดต่อไปนี้
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

Server Action ของ Next.js มี API ที่สะดวกในการเข้าถึงข้อมูลแบบฟอร์ม เช่น data.get("text") เพื่อรับค่าข้อความจากเพย์โหลดการส่งแบบฟอร์ม

หากต้องการใช้ Next.js Server Action เพื่อประมวลผลการส่งแบบฟอร์มรีวิว ให้ทำตามขั้นตอนต่อไปนี้

  1. ในไฟล์ src/components/ReviewDialog.jsx ให้ค้นหาแอตทริบิวต์ action ในองค์ประกอบ <form>
<form
  action={handleReviewFormSubmission}
  onSubmit={() => {
    handleClose();
  }}
>

ค่าแอตทริบิวต์ action หมายถึงฟังก์ชันที่คุณจะใช้ในขั้นตอนถัดไป

  1. ในไฟล์ src/app/actions.js ให้แทนที่ฟังก์ชัน handleReviewFormSubmission() ด้วยโค้ดต่อไปนี้
export async function handleReviewFormSubmission(data) {
  const { firebaseServerApp } = await getAuthenticatedAppForUser();
  const db = getFirestore(firebaseServerApp);

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

เพิ่มรีวิวร้านอาหาร

คุณได้ติดตั้งใช้งานการรองรับการส่งรีวิวแล้ว ตอนนี้คุณสามารถยืนยันได้ว่าระบบได้แทรกรีวิวลงใน Cloud Firestore อย่างถูกต้อง

หากต้องการเพิ่มรีวิวและยืนยันว่ารีวิวนั้นได้รับการแทรกลงใน Cloud Firestore แล้ว ให้ทำตามขั้นตอนต่อไปนี้

  1. สร้างคอมมิตพร้อมข้อความคอมมิต "อนุญาตให้ผู้ใช้ส่งรีวิวร้านอาหาร" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Allow users to submit restaurant reviews"
    
    git push
    
  2. เปิดหน้า App Hosting ในคอนโซล Firebase แล้วรอให้การเปิดตัวใหม่เสร็จสมบูรณ์
  3. รีเฟรชเว็บแอป แล้วเลือกร้านอาหารจากหน้าแรก
  4. คลิก 3e19beef78bb0d0e.png ในหน้าของร้านอาหาร
  5. เลือกการให้ดาว
  6. เขียนรีวิว
  7. คลิกส่ง รีวิวของคุณจะปรากฏที่ด้านบนของรายการรีวิว
  8. ใน Cloud Firestore ให้ค้นหาแผงเพิ่มเอกสารสำหรับเอกสารของร้านอาหารที่คุณรีวิว แล้วเลือกเอกสารนั้น
  9. ในแผงเริ่มรวบรวม ให้เลือกการให้คะแนน
  10. ในแผงเพิ่มเอกสาร ให้ค้นหาเอกสารเพื่อตรวจสอบว่ามีการแทรกตามที่คาดไว้

9. บันทึกไฟล์ที่ผู้ใช้อัปโหลดจากเว็บแอป

ในส่วนนี้ คุณจะเพิ่มฟังก์ชันเพื่อให้แทนที่รูปภาพที่เชื่อมโยงกับร้านอาหารได้เมื่อเข้าสู่ระบบ คุณอัปโหลดรูปภาพไปยัง Firebase Storage และอัปเดต URL ของรูปภาพในเอกสาร Cloud Firestore ที่แสดงถึงร้านอาหาร

หากต้องการบันทึกไฟล์ที่ผู้ใช้อัปโหลดจากเว็บแอป ให้ทำตามขั้นตอนต่อไปนี้

  1. ในไฟล์ src/components/Restaurant.jsx ให้สังเกตโค้ดที่ทำงานเมื่อผู้ใช้อัปโหลดไฟล์
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 });
}

คุณไม่จำเป็นต้องเปลี่ยนแปลงฟังก์ชันนี้ แต่คุณจะติดตั้งใช้งานลักษณะการทำงานของฟังก์ชัน updateRestaurantImage() ได้ในขั้นตอนต่อไปนี้

  1. ในไฟล์ src/lib/firebase/storage.js ให้แทนที่ฟังก์ชัน updateRestaurantImage() และ uploadImage() ด้วยโค้ดต่อไปนี้
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() ให้คุณแล้ว ฟังก์ชันนี้จะอัปเดตเอกสารร้านอาหารที่มีอยู่ใน Cloud Firestore ด้วย URL รูปภาพที่อัปเดตแล้ว

ยืนยันฟังก์ชันการอัปโหลดรูปภาพ

หากต้องการยืนยันว่ารูปภาพอัปโหลดตามที่คาดไว้ ให้ทำตามขั้นตอนต่อไปนี้

  1. สร้างคอมมิตพร้อมข้อความคอมมิตว่า "อนุญาตให้ผู้ใช้เปลี่ยนรูปภาพของร้านอาหารแต่ละร้าน" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Allow users to change each restaurants' photo"
    
    git push
    
  2. เปิดหน้า App Hosting ในคอนโซล Firebase แล้วรอให้การเปิดตัวใหม่เสร็จสมบูรณ์
  3. ในเว็บแอป ให้ตรวจสอบว่าคุณเข้าสู่ระบบแล้วและเลือกร้านอาหาร
  4. คลิก 7067eb41fea41ff0.png แล้วอัปโหลดรูปภาพจากระบบไฟล์ รูปภาพจะออกจากสภาพแวดล้อมในเครื่องและอัปโหลดไปยัง Cloud Storage รูปภาพจะปรากฏขึ้นทันทีหลังจากที่คุณอัปโหลด
  5. ไปที่ Cloud Storage สำหรับ Firebase
  6. ไปยังโฟลเดอร์ที่แสดงถึงร้านอาหาร รูปภาพที่คุณอัปโหลดจะอยู่ในโฟลเดอร์

6cf3f9e2303c931c.png

10. สรุปรีวิวร้านอาหารด้วย Generative AI

ในส่วนนี้ คุณจะเพิ่มฟีเจอร์สรุปรีวิวเพื่อให้ผู้ใช้ทราบได้อย่างรวดเร็วว่าทุกคนคิดอย่างไรกับร้านอาหารโดยไม่ต้องอ่านรีวิวทั้งหมด

จัดเก็บคีย์ Gemini API ใน Cloud Secret Manager

  1. หากต้องการใช้ Gemini API คุณจะต้องมีคีย์ API ไปที่ Google AI Studio แล้วคลิกสร้างคีย์ API
  2. ตั้งชื่อคีย์ตามต้องการ หากโปรเจ็กต์ของคุณไม่อยู่ในส่วนเลือกโปรเจ็กต์ที่นำเข้า ให้คลิกนำเข้าโปรเจ็กต์ เลือกโปรเจ็กต์ในรายการ แล้วคลิกนำเข้า สุดท้าย ให้เลือกโปรเจ็กต์ในส่วนเลือกโปรเจ็กต์ที่นำเข้า แล้วคลิกสร้างคีย์
  3. App Hosting ผสานรวมกับ Cloud Secret Manager เพื่อให้คุณจัดเก็บค่าที่มีความละเอียดอ่อน เช่น คีย์ API ได้อย่างปลอดภัย
    1. ในเทอร์มินัล ให้เรียกใช้คำสั่งเพื่อสร้างข้อมูลลับใหม่
    firebase apphosting:secrets:set GEMINI_API_KEY
    
    1. เมื่อระบบแจ้งให้ระบุค่าลับ ให้คัดลอกและวางคีย์ Gemini API จาก Google AI Studio
    2. เมื่อระบบถามว่ารหัสลับใหม่นี้ใช้สำหรับการทดสอบในเวอร์ชันที่ใช้งานจริงหรือการทดสอบในเครื่อง ให้เลือก "เวอร์ชันที่ใช้งานจริง"
    3. เมื่อระบบถามว่าต้องการให้สิทธิ์เข้าถึงเพื่อให้บัญชีบริการของแบ็กเอนด์เข้าถึงข้อมูลลับได้หรือไม่ ให้เลือก "ใช่"
    4. เมื่อระบบถามว่าควรเพิ่มข้อมูลลับใหม่ลงใน apphosting.yaml ไหม ให้ป้อน Y เพื่อยอมรับ

ตอนนี้ระบบได้จัดเก็บคีย์ Gemini API ของคุณไว้อย่างปลอดภัยใน Cloud Secret Manager และแบ็กเอนด์ App Hosting ของคุณสามารถเข้าถึงได้

ติดตั้งใช้งานคอมโพเนนต์สรุปรีวิว

  1. ใน src/components/Reviews/ReviewSummary.jsx ให้แทนที่ฟังก์ชัน GeminiSummary ด้วยโค้ดต่อไปนี้
    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. สร้างคอมมิตที่มีข้อความคอมมิตว่า "ใช้ AI เพื่อสรุปรีวิว" แล้วพุชไปยังที่เก็บ GitHub
    git add .
    
    git commit -m "Use AI to summarize reviews"
    
    git push
    
  3. เปิดหน้า App Hosting ในคอนโซล Firebase แล้วรอให้การเปิดตัวใหม่เสร็จสมบูรณ์
  4. เปิดหน้าเว็บของร้านอาหาร ที่ด้านบน คุณจะเห็นสรุปรีวิวทั้งหมดในหน้าเป็นประโยคเดียว
  5. เพิ่มรีวิวใหม่และรีเฟรชหน้าเว็บ คุณควรเห็นการเปลี่ยนแปลงสรุป

11. ยกเลิกการเผยแพร่เว็บไซต์ App Hosting

หลังจากทำ Codelab นี้เสร็จแล้ว หากไม่ต้องการใช้แอปต่อ คุณสามารถยกเลิกการเผยแพร่แอปเพื่อให้แน่ใจว่าไม่มีใครเข้าถึงทรัพยากร Firestore, Storage และ Gemini ของคุณได้ ทั้งนี้คุณเผยแพร่อีกครั้งได้ทุกเมื่อ

วิธียกเลิกการเผยแพร่เว็บไซต์ App Hosting

  1. เปิด App Hosting ในคอนโซล Firebase
  2. ค้นหาแบ็กเอนด์ของแอป แล้วคลิกดู
  3. ในส่วนข้อมูลแบ็กเอนด์ ให้คลิกจัดการข้างโดเมน ซึ่งจะโหลดหน้าโดเมน
  4. คลิกไอคอนเพิ่มเติม (จุดแนวตั้ง 3 จุด) ข้างโดเมน เลือกปิดใช้โดเมน แล้วคลิกปิดใช้เพื่อยืนยัน

12. บทสรุป

ยินดีด้วย คุณได้เรียนรู้วิธีใช้ Firebase เพื่อเพิ่มฟีเจอร์และฟังก์ชันการทํางานลงในแอป Next.js โดยเฉพาะอย่างยิ่ง คุณได้ใช้สิ่งต่อไปนี้

  • Firebase App Hosting เพื่อสร้างและติดตั้งใช้งานโค้ด Next.js โดยอัตโนมัติทุกครั้งที่คุณพุชไปยังกิ่งที่กำหนดค่าไว้
  • การตรวจสอบสิทธิ์ Firebase เพื่อเปิดใช้ฟังก์ชันการลงชื่อเข้าใช้และลงชื่อออก
  • Cloud Firestore สำหรับข้อมูลร้านอาหารและข้อมูลรีวิวร้านอาหาร
  • Cloud Storage for Firebase สำหรับรูปภาพร้านอาหาร

ดูข้อมูลเพิ่มเติม