היכרות עם Firebase לאינטרנט

1. סקירה כללית

ב-codelab הזה תלמדו כמה מהיסודות של Firebase כדי ליצור אפליקציות אינטרנט אינטראקטיביות. תבנו אפליקציה לצ'אט של ספר אורחים ואישור השתתפות באירוע באמצעות כמה מוצרים של Firebase.

צילום מסך של השלב הזה

מה תלמדו

  • אימות משתמשים באמצעות אימות ב-Firebase ו-FirebaseUI.
  • סנכרון נתונים באמצעות Cloud Firestore.
  • כתיבת כללי אבטחה ב-Firebase כדי לאבטח מסד נתונים.

מה צריך

  • דפדפן לבחירתכם, כמו Chrome.
  • גישה ל-stackblitz.com (לא נדרש חשבון או כניסה).
  • חשבון Google, כמו חשבון Gmail. מומלץ להשתמש בחשבון האימייל שבו אתם כבר משתמשים לחשבון GitHub. כך תוכלו להשתמש בתכונות מתקדמות ב-StackBlitz.
  • קוד לדוגמה של ה-codelab. הסבר על קבלת הקוד מופיע בשלב הבא.

2. קבלת קוד ההתחלה

ב-codelab הזה, תיצרו אפליקציה באמצעות StackBlitz, כלי עריכה אונליין שמשולבים בו כמה תהליכי עבודה של Firebase. לא צריך להתקין תוכנה או ליצור חשבון מיוחד ב-StackBlitz.

ב-StackBlitz אפשר לשתף פרויקטים עם אחרים. אנשים אחרים שיש להם את כתובת ה-URL של פרויקט StackBlitz יכולים לראות את הקוד שלכם ולבצע Fork לפרויקט, אבל הם לא יכולים לערוך את פרויקט StackBlitz.

  1. כדי להגיע לקוד ההתחלתי, עוברים לכתובת ה-URL הבאה: https://stackblitz.com/edit/firebase-gtk-web-start
  2. בחלק העליון של דף StackBlitz, לוחצים על Fork:

צילום מסך של השלב הזה

עכשיו יש לכם עותק של קוד ההתחלה כפרויקט StackBlitz משלכם, עם שם ייחודי וכתובת URL ייחודית. כל הקבצים והשינויים שלכם נשמרים בפרויקט הזה ב-StackBlitz.

3. עריכת פרטי האירוע

חומרי ההתחלה של ה-codelab הזה מספקים מבנה מסוים לאפליקציית האינטרנט, כולל כמה גיליונות סגנונות וכמה מאגרי HTML לאפליקציה. בהמשך ה-codelab, תגדירו את המאגרים האלה ב-Firebase.

כדי להתחיל, נסביר על הממשק של StackBlitz.

  1. ב-StackBlitz, פותחים את הקובץ index.html.
  2. מאתרים את event-details-container ואת description-container ומנסים לערוך כמה פרטים של אירוע.

כשעורכים את הטקסט, טעינת הדף האוטומטית ב-StackBlitz מציגה את פרטי האירוע החדשים. מגניב, נכון?

<!-- ... -->

<div id="app">
  <img src="..." />

  <section id="event-details-container">
     <h1>Firebase Meetup</h1>

     <p><i class="material-icons">calendar_today</i> October 30</p>
     <p><i class="material-icons">location_city</i> San Francisco</p>

  </section>

  <hr>

  <section id="firebaseui-auth-container"></section>

  <section id="description-container">
     <h2>What we'll be doing</h2>
     <p>Join us for a day full of Firebase Workshops and Pizza!</p>
  </section>
</div>

<!-- ... -->

תצוגה מקדימה של האפליקציה אמורה להיראות כך:

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

4. יצירה והגדרה של פרויקט Firebase

הצגת פרטי האירוע היא דבר טוב למשתתפים, אבל הצגת האירועים בלבד לא מועילה לאף אחד. בשלב הבא, נוסיף לאפליקציה פונקציונליות דינמית. כדי לעשות את זה, צריך לקשר את Firebase לאפליקציה. כדי להתחיל להשתמש ב-Firebase, צריך ליצור ולהגדיר פרויקט ב-Firebase.

יצירת פרויקט Firebase

  1. נכנסים למסוף Firebase באמצעות חשבון Google.
  2. לוחצים על הלחצן ליצירת פרויקט חדש ומזינים שם לפרויקט (לדוגמה, Firebase-Web-Codelab).
  3. לוחצים על המשך.
  4. אם מוצגת בקשה לעשות זאת, קוראים ומאשרים את התנאים של Firebase, ואז לוחצים על המשך.
  5. (אופציונלי) מפעילים את העזרה מבוססת-AI במסוף Firebase (שנקראת Gemini ב-Firebase).
  6. ב-codelab הזה לא צריך להשתמש ב-Google Analytics, ולכן משביתים את האפשרות Google Analytics.
  7. לוחצים על יצירת פרויקט, מחכים שהפרויקט יוקצה ולוחצים על המשך.

מידע נוסף על פרויקטים ב-Firebase זמין במאמר הסבר על פרויקטים ב-Firebase.

הפעלה והגדרה של מוצרי Firebase במסוף

האפליקציה שאתם בונים משתמשת בכמה מוצרים של Firebase שזמינים לאפליקציות אינטרנט:

  • אימות ב-Firebase וממשק המשתמש של Firebase כדי לאפשר למשתמשים להיכנס לאפליקציה בקלות.
  • Cloud Firestore כדי לשמור נתונים מובנים בענן ולקבל הודעה מיידית כשמתבצעים שינויים בנתונים.
  • כללי אבטחה של Firebase כדי לאבטח את מסד הנתונים.

כדי להשתמש בחלק מהמוצרים האלה, צריך לבצע הגדרה מיוחדת או להפעיל אותם באמצעות מסוף Firebase.

הפעלת כניסה באמצעות אימייל ב-Firebase Authentication

כדי לאפשר למשתמשים להיכנס לאפליקציית האינטרנט, תשתמשו בשיטת הכניסה אימייל/סיסמה ב-codelab הזה:

  1. בחלונית הימנית של מסוף Firebase, לוחצים על Build (פיתוח) > Authentication (אימות). לוחצים על שנתחיל?. עכשיו אתם נמצאים במרכז הבקרה של האימות, שבו אפשר לראות את המשתמשים שנרשמו, להגדיר ספקי כניסה ולנהל את ההגדרות.

    צילום מסך של השלב הזה

  2. בוחרים בכרטיסייה Sign-in method (או לוחצים כאן כדי לעבור ישירות לכרטיסייה).

    צילום מסך של השלב הזה

  3. לוחצים על אימייל/סיסמה באפשרויות של הספק, מעבירים את המתג למצב הפעלה ואז לוחצים על שמירה.

    צילום מסך של השלב הזה

הגדרה של Cloud Firestore

אפליקציית האינטרנט משתמשת ב-Cloud Firestore כדי לשמור הודעות בצ'אט ולקבל הודעות חדשות בצ'אט.

כך מגדירים את Cloud Firestore בפרויקט Firebase:

  1. בחלונית הימנית במסוף Firebase, מרחיבים את Build ובוחרים באפשרות Firestore database.
  2. לוחצים על יצירת מסד נתונים.
  3. משאירים את הערך (default) בשדה מזהה מסד הנתונים.
  4. בוחרים מיקום למסד הנתונים ולוחצים על הבא.
    באפליקציה אמיתית, כדאי לבחור מיקום שקרוב למשתמשים.
  5. לוחצים על התחלה במצב בדיקה. קוראים את כתב הוויתור בנוגע לכללי האבטחה.
    בהמשך ה-codelab הזה, תוסיפו כללי אבטחה כדי לאבטח את הנתונים. אל תפיצו או תחשפו אפליקציה באופן ציבורי בלי להוסיף כללי אבטחה למסד הנתונים.
  6. לוחצים על יצירה.

5. הוספה והגדרה של Firebase

אחרי שיצרתם את פרויקט Firebase והפעלתם כמה שירותים, צריך להגדיר בקוד שאתם רוצים להשתמש ב-Firebase, וגם לציין באיזה פרויקט Firebase אתם רוצים להשתמש.

הוספת ספריות Firebase

כדי להשתמש ב-Firebase באפליקציה, צריך להוסיף את ספריות Firebase לאפליקציה. יש כמה דרכים לעשות את זה, כפי שמתואר במסמכי התיעוד של Firebase. לדוגמה, אפשר להוסיף את הספריות מ-CDN של Google, או להתקין אותן באופן מקומי באמצעות npm ואז לארוז אותן באפליקציה אם משתמשים ב-Browserify.

‫StackBlitz מספקת חבילה אוטומטית, כך שאפשר להוסיף את ספריות Firebase באמצעות הצהרות ייבוא. תשתמשו בגרסאות המודולריות (גרסה 9) של הספריות, שעוזרות להקטין את הגודל הכולל של דף האינטרנט באמצעות תהליך שנקרא 'הסרת קוד שלא בשימוש'. במסמכי התיעוד מפורט מידע נוסף על ערכות SDK מודולריות.

כדי ליצור את האפליקציה הזו, משתמשים בספריות Firebase Authentication,‏ FirebaseUI ו-Cloud Firestore. ב-codelab הזה, הצהרות הייבוא הבאות כבר כלולות בחלק העליון של הקובץ index.js, ואנחנו נייבא עוד שיטות מכל ספריית Firebase בהמשך:

// Import stylesheets
import './style.css';

// Firebase App (the core Firebase SDK) is always required
import { initializeApp } from 'firebase/app';

// Add the Firebase products and methods that you want to use
import {} from 'firebase/auth';
import {} from 'firebase/firestore';

import * as firebaseui from 'firebaseui';

איך מוסיפים אפליקציית אינטרנט של Firebase לפרויקט Firebase

  1. במסוף Firebase, לוחצים על Project Overview (סקירת הפרויקט) בפינה הימנית העליונה כדי לעבור לדף הסקירה הכללית של הפרויקט.
  2. במרכז הדף 'סקירה כללית' של הפרויקט, לוחצים על סמל האינטרנט סמל של אפליקציית אינטרנטכדי ליצור אפליקציית אינטרנט חדשה של Firebase.

    צילום מסך של השלב הזה

  3. רושמים את האפליקציה עם הכינוי Web App.
  4. במסגרת ה-codelab הזה, אל תסמנו את התיבה לצד Also set up Firebase Hosting for this app (הגדרת אירוח ב-Firebase גם לאפליקציה הזו). בשלב הזה תשתמשו בחלונית התצוגה המקדימה של StackBlitz.
  5. לוחצים על Register app (רישום האפליקציה).

    צילום מסך של השלב הזה

  6. מעתיקים את אובייקט ההגדרה של Firebase ללוח.

    צילום מסך של השלב הזה

  7. לוחצים על Continue to console (המשך למסוף). מוסיפים את אובייקט ההגדרה של Firebase לאפליקציה:
  8. חוזרים ל-StackBlitz ועוברים לקובץ index.js.
  9. מאתרים את שורת ההערה Add Firebase project configuration object here ומדביקים את קטע ההגדרות ממש מתחת להערה.
  10. מוסיפים את הקריאה לפונקציה initializeApp כדי להגדיר את Firebase באמצעות ההגדרה הייחודית של פרויקט Firebase.
    // ...
    // Add Firebase project configuration object here
    const firebaseConfig = {
      apiKey: "random-unique-string",
      authDomain: "your-projectId.firebaseapp.com",
      databaseURL: "https://your-projectId.firebaseio.com",
      projectId: "your-projectId",
      storageBucket: "your-projectId.firebasestorage.app",
      messagingSenderId: "random-unique-string",
      appId: "random-unique-string",
    };
    
    // Initialize Firebase
    initializeApp(firebaseConfig);
    

6. הוספת כניסה של משתמש (אישור השתתפות)

אחרי שמוסיפים את Firebase לאפליקציה, אפשר להגדיר לחצן לאישור השתתפות שרושם אנשים באמצעות Firebase Authentication.

אימות משתמשים באמצעות כניסה עם כתובת אימייל ו-FirebaseUI

תצטרכו להוסיף לחתימה לחצן לאישור השתתפות, שיבקש מהמשתמש להיכנס באמצעות כתובת האימייל שלו. אפשר לעשות את זה על ידי קישור של FirebaseUI ללחצן אישור הגעה.FirebaseUI היא ספרייה שמספקת ממשק משתמש מוכן מראש על גבי Firebase Auth.

‫FirebaseUI דורש הגדרה (אפשרויות ההגדרה מפורטות במסמכי התיעוד) שמבצעת שני דברים:

  • הפונקציה הזו מציינת ל-FirebaseUI שרוצים להשתמש בשיטת הכניסה Email/Password.
  • מטפלת בקריאה החוזרת לכניסה מוצלחת ומחזירה false כדי למנוע הפניה אוטומטית. אתם לא רוצים שהדף יתרענן כי אתם בונים אפליקציית אינטרנט של דף יחיד.

הוספת הקוד לאתחול FirebaseUI Auth

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק העליון, מאתרים את הצהרת הייבוא firebase/auth, ואז מוסיפים את getAuth ואת EmailAuthProvider, כך:
    // ...
    // Add the Firebase products and methods that you want to use
    import { getAuth, EmailAuthProvider } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. שומרים הפניה לאובייקט האימות מיד אחרי initializeApp, כך:
    initializeApp(firebaseConfig);
    auth = getAuth();
    
  4. שימו לב שההגדרה של FirebaseUI כבר מופיעה בקוד ההתחלתי. הוא כבר מוגדר לשימוש בספק אימות האימייל.
  5. בתחתית הפונקציה main() ב-index.js, מוסיפים את הצהרת האתחול של FirebaseUI, כך:
    async function main() {
      // ...
    
      // Initialize the FirebaseUI widget using Firebase
      const ui = new firebaseui.auth.AuthUI(auth);
    }
    main();
    
    

הוספת לחצן לאישור השתתפות ל-HTML

  1. ב-StackBlitz, עוברים לקובץ index.html.
  2. מוסיפים את קוד ה-HTML של לחצן אישור ההגעה בתוך התג event-details-container, כמו בדוגמה שלמטה.

    חשוב להשתמש באותם ערכי id שמוצגים בהמשך, כי בקובץ index.js כבר יש hooks למזהים הספציפיים האלה.

    שימו לב שבקובץ index.html יש מאגר תגים עם המזהה firebaseui-auth-container. זה המזהה שתעבירו ל-FirebaseUI כדי לשמור את פרטי הכניסה שלכם.
    <!-- ... -->
    
    <section id="event-details-container">
        <!-- ... -->
        <!-- ADD THE RSVP BUTTON HERE -->
        <button id="startRsvp">RSVP</button>
    </section>
    <hr>
    <section id="firebaseui-auth-container"></section>
    <!-- ... -->
    
    תצוגה מקדימה של אפליקציה

    צילום מסך של השלב הזה

  3. מגדירים מאזין על לחצן האישור להשתתפות באירוע ומפעילים את פונקציית ההתחלה של FirebaseUI. הפעולה הזו אומרת ל-FirebaseUI שאתם רוצים לראות את חלון הכניסה.

    מוסיפים את הקוד הבא לחלק התחתון של הפונקציה main() ב-index.js:
    async function main() {
      // ...
    
      // Listen to RSVP button clicks
      startRsvpButton.addEventListener("click",
       () => {
            ui.start("#firebaseui-auth-container", uiConfig);
      });
    }
    main();
    

בדיקת הכניסה לאפליקציה

  1. בחלון התצוגה המקדימה של StackBlitz, לוחצים על הלחצן לאישור ההגעה כדי להיכנס לאפליקציה.
    • ב-codelab הזה, אפשר להשתמש בכל כתובת אימייל, אפילו בכתובת אימייל מזויפת, כי לא מגדירים שלב לאימות כתובת אימייל.
    • אם מופיעה הודעת שגיאה עם הכיתוב auth/operation-not-allowed או The given sign-in provider is disabled for this Firebase project, צריך לוודא שהפעלתם את התחברות באמצעות אימייל וסיסמה כספק התחברות במסוף Firebase.
    תצוגה מקדימה של אפליקציה

    צילום מסך של השלב הזה

  2. נכנסים אל לוח הבקרה של אימות במסוף Firebase. בכרטיסייה משתמשים אמורים להופיע פרטי החשבון שהזנתם כדי להיכנס לאפליקציה.

    צילום מסך של השלב הזה

הוספת מצב אימות לממשק המשתמש

בשלב הבא, מוודאים שממשק המשתמש משקף את העובדה שאתם מחוברים לחשבון.

תשתמשו בפונקציית הקריאה החוזרת (callback) של מאזין המצב של אימות ב-Firebase, שמקבלת הודעה בכל פעם שסטטוס הכניסה של המשתמש משתנה. אם יש כרגע משתמש מחובר, האפליקציה תהפוך את הלחצן 'אישור השתתפות' ללחצן 'יציאה'.

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק העליון, מאתרים את הצהרת הייבוא firebase/auth, ואז מוסיפים את signOut ואת onAuthStateChanged, כך:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {} from 'firebase/firestore';
    
  3. מוסיפים את הקוד הבא לתחתית הפונקציה main():
    async function main() {
      // ...
    
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
        } else {
          startRsvpButton.textContent = 'RSVP';
        }
      });
    }
    main();
    
  4. במאזין ללחצן, בודקים אם יש משתמש נוכחי ומנתקים אותו מהחשבון. כדי לעשות את זה, מחליפים את startRsvpButton.addEventListener הנוכחי בקוד הבא:
    // ...
    // Called when the user clicks the RSVP button
    startRsvpButton.addEventListener('click', () => {
      if (auth.currentUser) {
        // User is signed in; allows user to sign out
        signOut(auth);
      } else {
        // No user is signed in; allows user to sign in
        ui.start('#firebaseui-auth-container', uiConfig);
      }
    });
    

עכשיו הלחצן באפליקציה אמור להציג את האפשרות התנתקות, וכשלוחצים עליו הוא אמור לחזור לאפשרות אישור השתתפות.

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

7. כתיבת הודעות ל-Cloud Firestore

זה נהדר לדעת שהמשתמשים מגיעים, אבל כדאי לתת לאורחים עוד משהו לעשות באפליקציה. מה אם הם יוכלו להשאיר הודעות בספר האורחים? הם יכולים לשתף למה הם מתרגשים להגיע או את מי הם מקווים לפגוש.

כדי לאחסן את ההודעות בצ'אט שהמשתמשים כותבים באפליקציה, תשתמשו ב-Cloud Firestore.

מודל נתונים

‫Cloud Firestore הוא מסד נתונים מסוג NoSQL, והנתונים שמאוחסנים בו מחולקים לקולקציות, מסמכים, שדות וקולקציות משנה. כל הודעה בצ'אט תישמר כמסמך באוסף ברמה העליונה שנקרא guestbook.

תרשים של מודל הנתונים של Firestore שבו מוצג אוסף של ספר אורחים עם כמה מסמכי הודעות

הוספת הודעות ל-Firestore

בקטע הזה מוסיפים את הפונקציונליות שמאפשרת למשתמשים לכתוב הודעות חדשות למסד הנתונים. קודם מוסיפים את קוד ה-HTML של רכיבי ממשק המשתמש (שדה ההודעה ולחצן השליחה). לאחר מכן מוסיפים את הקוד שמקשר בין הרכיבים האלה למסד הנתונים.

כדי להוסיף את רכיבי ממשק המשתמש של שדה הודעה ולחצן שליחה:

  1. ב-StackBlitz, עוברים לקובץ index.html.
  2. מחפשים את התג guestbook-container ומוסיפים את קוד ה-HTML הבא כדי ליצור טופס עם שדה קלט להודעה ולחצן שליחה.
    <!-- ... -->
    
     <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form id="leave-message">
         <label>Leave a message: </label>
         <input type="text" id="message">
         <button type="submit">
           <i class="material-icons">send</i>
           <span>SEND</span>
         </button>
       </form>
    
     </section>
    
    <!-- ... -->
    

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

משתמש שלוחץ על הלחצן SEND (שליחה) יפעיל את קטע הקוד שבהמשך. התוכן של שדה הקלט של ההודעה מתווסף לאוסף guestbook של מסד הנתונים. באופן ספציפי, השיטה addDoc מוסיפה את תוכן ההודעה למסמך חדש (עם מזהה שנוצר באופן אוטומטי) לאוסף guestbook.

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק העליון, מאתרים את הצהרת הייבוא firebase/firestore ומוסיפים את getFirestore, addDoc ו-collection, כך:
    // ...
    
    // Add the Firebase products and methods that you want to use
    import {
      getAuth,
      EmailAuthProvider,
      signOut,
      onAuthStateChanged
    } from 'firebase/auth';
    
    import {
      getFirestore,
      addDoc,
      collection
    } from 'firebase/firestore';
    
  3. עכשיו נשמור הפניה לאובייקט db של Firestore מיד אחרי initializeApp:
    initializeApp(firebaseConfig);
    auth = getAuth();
    db = getFirestore();
    
  4. בתחתית הפונקציה main(), מוסיפים את הקוד הבא.

    שימו לב ש-auth.currentUser.uid הוא הפניה למזהה הייחודי שנוצר באופן אוטומטי ומוקצה על ידי אימות ב-Firebase לכל המשתמשים שמחוברים לחשבון.
    async function main() {
      // ...
    
      // Listen to the form submission
      form.addEventListener('submit', async e => {
        // Prevent the default form redirect
        e.preventDefault();
        // Write a new message to the database collection "guestbook"
        addDoc(collection(db, 'guestbook'), {
          text: input.value,
          timestamp: Date.now(),
          name: auth.currentUser.displayName,
          userId: auth.currentUser.uid
        });
        // clear message input field
        input.value = '';
        // Return false to avoid redirect
        return false;
      });
    }
    main();
    

הצגת ספר האורחים רק למשתמשים שמחוברים לחשבון

אתם לא רוצים שכל אחד יוכל לראות את הצ'אט של המשתתפים. אחת הדרכים לאבטח את הצ'אט היא לאפשר רק למשתמשים שמחוברים לחשבון לראות את ספר האורחים. עם זאת, כדי להגן על מסד הנתונים של האפליקציות שלכם, כדאי להשתמש גם בכללי האבטחה של Firebase. (מידע נוסף על כללי אבטחה מופיע בהמשך ה-codelab).

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. עורכים את onAuthStateChanged המאזין כדי להסתיר ולהציג את ספר האורחים.
    // ...
    
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
      }
    });
    

בדיקה של שליחת הודעות

  1. מוודאים שנכנסתם לחשבון באפליקציה.
  2. כותבים הודעה, למשל "היי", ואז לוחצים על שליחה.

הפעולה הזו כותבת את ההודעה למסד הנתונים של Cloud Firestore. עם זאת, ההודעה עדיין לא תוצג באפליקציית האינטרנט בפועל, כי עדיין צריך להטמיע את אחזור הנתונים. את זה עושים אחר כך.

אבל תוכלו לראות את ההודעה החדשה במסוף Firebase.

במסוף Firebase, במרכז הבקרה של Firestore Database, אמור להופיע האוסף guestbook עם ההודעה החדשה שהוספתם. אם תמשיכו לשלוח הודעות, אוסף הספרים לאורחים יכיל הרבה מסמכים, כמו זה:

מסוף Firebase

צילום מסך של השלב הזה

8. קריאת ההודעות

סנכרון הודעות

נחמד שאורחים יכולים לכתוב הודעות למסד הנתונים, אבל הם עדיין לא יכולים לראות אותן באפליקציה.

כדי להציג הודעות, צריך להוסיף מאזינים שמופעלים כשנתונים משתנים, ואז ליצור רכיב בממשק המשתמש שמציג הודעות חדשות.

מוסיפים קוד שמאזין להודעות חדשות שנוספו מהאפליקציה. קודם מוסיפים קטע ב-HTML להצגת הודעות:

  1. ב-StackBlitz, עוברים לקובץ index.html.
  2. ב-guestbook-container, מוסיפים קטע חדש עם המזהה guestbook.
    <!-- ... -->
    
      <section id="guestbook-container">
       <h2>Discussion</h2>
    
       <form><!-- ... --></form>
    
       <section id="guestbook"></section>
    
     </section>
    
    <!-- ... -->
    

לאחר מכן, רושמים את ה-listener שמקשיב לשינויים שבוצעו בנתונים:

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק העליון, מאתרים את הצהרת הייבוא firebase/firestore ומוסיפים את query, orderBy ו-onSnapshot, כך:
    // ...
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot
    } from 'firebase/firestore';
    
  3. בתחתית הפונקציה main(), מוסיפים את הקוד הבא כדי ליצור לולאה שתעבור על כל המסמכים (הודעות בספר האורחים) במסד הנתונים. כדי לקבל מידע נוסף על מה שקורה בקוד הזה, אפשר לקרוא את המידע שמתחת לקטע הקוד.
    async function main() {
      // ...
    
      // Create query for messages
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    main();
    

כדי להאזין להודעות במסד הנתונים, יצרתם שאילתה באוסף ספציפי באמצעות הפונקציה collection. הקוד שלמעלה מאזין לשינויים באוסף guestbook, שבו מאוחסנות הודעות הצ'אט. ההודעות מסודרות גם לפי תאריך, וההודעות החדשות ביותר מוצגות למעלה באמצעות orderBy('timestamp', 'desc').

הפונקציה onSnapshot מקבלת שני פרמטרים: השאילתה שבה רוצים להשתמש ופונקציית קריאה חוזרת. פונקציית הקריאה החוזרת מופעלת כשמתבצעים שינויים במסמכים שתואמים לשאילתה. לדוגמה, אם הודעה נמחקת, משתנה או מתווספת. מידע נוסף זמין במאמרי העזרה בנושא Cloud Firestore.

בדיקת סנכרון ההודעות

‫Cloud Firestore מסנכרן את הנתונים באופן אוטומטי ומיידי עם לקוחות שמנויים למסד הנתונים.

  • ההודעות שיצרתם קודם במסד הנתונים אמורות להופיע באפליקציה. אתם יכולים לכתוב הודעות חדשות, והן אמורות להופיע באופן מיידי.
  • אם פותחים את סביבת העבודה בכמה חלונות או כרטיסיות, ההודעות יסונכרנו בזמן אמת בין הכרטיסיות.
  • (אופציונלי) אפשר לנסות למחוק, לשנות או להוסיף הודעות חדשות באופן ידני ישירות בקטע Database במסוף Firebase. כל השינויים אמורים להופיע בממשק המשתמש.

כל הכבוד! אתם קוראים מסמכי Cloud Firestore באפליקציה שלכם!

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

9. הגדרת כללי אבטחה בסיסיים

הגדרתם את Cloud Firestore לשימוש במצב בדיקה, כלומר מסד הנתונים שלכם פתוח לקריאה ולכתיבה. עם זאת, מומלץ להשתמש במצב בדיקה רק בשלבים מוקדמים מאוד של הפיתוח. מומלץ להגדיר כללי אבטחה למסד הנתונים במהלך פיתוח האפליקציה. האבטחה צריכה להיות חלק בלתי נפרד מהמבנה וההתנהגות של האפליקציה.

כללי אבטחה מאפשרים לכם לשלוט בגישה למסמכים ולאוספים במסד הנתונים. תחביר הכללים הגמיש מאפשר לכם ליצור כללים שתואמים לכל דבר, החל מכל פעולות הכתיבה למסד הנתונים כולו ועד לפעולות במסמך ספציפי.

אפשר לכתוב כללי אבטחה ל-Cloud Firestore במסוף Firebase:

  1. בקטע Build (פיתוח) במסוף Firebase, לוחצים על Firestore Database (מסד נתונים של Firestore) ואז בוחרים בכרטיסייה Rules (כללים) (או לוחצים כאן כדי לעבור ישירות לכרטיסייה Rules).
  2. אלה כללי האבטחה שמוגדרים כברירת מחדל, עם הגבלת זמן לגישה ציבורית של כמה שבועות מהיום.

צילום מסך של השלב הזה

זיהוי אוספים

קודם כל, מזהים את האוספים שהאפליקציה כותבת אליהם נתונים.

  1. מוחקים את הסעיף הקיים match /{document=**}, כך שהכללים ייראו כך:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
      }
    }
    
  2. ב-match /databases/{database}/documents, מזהים את האוסף שרוצים לאבטח:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
         // You'll add rules here in the next step.
      }
    }
    

הוספת כללי אבטחה

מכיוון שהשתמשתם ב-UID של האימות כשדה בכל מסמך בספר האורחים, אתם יכולים לקבל את ה-UID של האימות ולוודא שלכל מי שמנסה לכתוב למסמך יש UID תואם של אימות.

  1. מוסיפים את כללי הקריאה והכתיבה לקבוצת הכללים, כמו שמוצג בהמשך:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
            if request.auth.uid == request.resource.data.userId;
        }
      }
    }
    
  2. לוחצים על פרסום כדי לפרוס את הכללים החדשים.עכשיו, בספר האורחים, רק משתמשים מחוברים יכולים לקרוא הודעות (כל הודעה!), אבל אפשר ליצור הודעה רק באמצעות מזהה המשתמש. בנוסף, אסור לערוך או למחוק הודעות.

הוספת כללי אימות

  1. מוסיפים אימות נתונים כדי לוודא שכל השדות הצפויים מופיעים במסמך:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /guestbook/{entry} {
          allow read: if request.auth.uid != null;
          allow create:
          if request.auth.uid == request.resource.data.userId
              && "name" in request.resource.data
              && "text" in request.resource.data
              && "timestamp" in request.resource.data;
        }
      }
    }
    
  2. לוחצים על פרסום כדי לפרוס את הכללים החדשים.

איפוס הגדרות מסוג listener

האפליקציה מאפשרת כניסה רק למשתמשים מאומתים, ולכן צריך להעביר את השאילתה של ספר האורחים firestore אל מאזין האימות. אחרת, יתרחשו שגיאות בהרשאות והאפליקציה תנותק כשהמשתמש יתנתק.

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. מושכים את אוסף onSnapshot listener של ספר האורחים לפונקציה חדשה בשם subscribeGuestbook. בנוסף, צריך להקצות את התוצאות של הפונקציה onSnapshot למשתנה guestbookListener. ‫

    הפונקציה של onSnapshot listener מחזירה פונקציית ביטול הרשמה שאפשר להשתמש בה כדי לבטל את ה-listener של התמונה בהמשך.
    // ...
    // Listen to guestbook updates
    function subscribeGuestbook() {
      const q = query(collection(db, 'guestbook'), orderBy('timestamp', 'desc'));
      guestbookListener = onSnapshot(q, snaps => {
        // Reset page
        guestbook.innerHTML = '';
        // Loop through documents in database
        snaps.forEach(doc => {
          // Create an HTML entry for each document and add it to the chat
          const entry = document.createElement('p');
          entry.textContent = doc.data().name + ': ' + doc.data().text;
          guestbook.appendChild(entry);
        });
      });
    }
    
  3. מוסיפים פונקציה חדשה מתחת בשם unsubscribeGuestbook. בודקים אם המשתנה guestbookListener הוא לא null, ואז מפעילים את הפונקציה כדי לבטל את ה-listener.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

לבסוף, מוסיפים את הפונקציות החדשות לonAuthStateChanged callback.

  1. לוחצים על סמל ההוספה subscribeGuestbook() בתחתית if (user).
  2. מוסיפים unsubscribeGuestbook() בתחתית ההצהרה else.
    // ...
    // Listen to the current Auth state
    onAuthStateChanged(auth, user => {
      if (user) {
        startRsvpButton.textContent = 'LOGOUT';
        // Show guestbook to logged-in users
        guestbookContainer.style.display = 'block';
        // Subscribe to the guestbook collection
        subscribeGuestbook();
      } else {
        startRsvpButton.textContent = 'RSVP';
        // Hide guestbook for non-logged-in users
        guestbookContainer.style.display = 'none';
        // Unsubscribe from the guestbook collection
        unsubscribeGuestbook();
      }
    });
    

10. שלב בונוס: תרגול של מה שלמדתם

הקלטת סטטוס אישור ההשתתפות של משתתף

בשלב הזה, האפליקציה מאפשרת לאנשים להתחיל צ'אט אם הם מתעניינים באירוע. בנוסף, הדרך היחידה לדעת אם מישהו יגיע היא אם הוא יפרסם את זה בצ'אט. כדאי להתארגן ולעדכן את האורחים כמה אנשים מגיעים.

תוסיפו מתג להרשמה של אנשים שרוצים להשתתף באירוע, ואז תאספו נתונים על מספר האנשים שמגיעים.

  1. ב-StackBlitz, עוברים לקובץ index.html.
  2. ב-guestbook-container, מוסיפים קבוצה של לחצני YES ו-NO, כך:
    <!-- ... -->
      <section id="guestbook-container">
       <h2>Are you attending?</h2>
         <button id="rsvp-yes">YES</button>
         <button id="rsvp-no">NO</button>
    
       <h2>Discussion</h2>
    
       <!-- ... -->
    
     </section>
    <!-- ... -->
    

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

בשלב הבא, רושמים את מאזין הלחיצות על הלחצנים. אם המשתמש לוחץ על כן, משתמשים ב-UID של האימות כדי לשמור את התגובה במסד הנתונים.

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק העליון, מאתרים את הצהרת הייבוא firebase/firestore ומוסיפים את doc, setDoc ו-where, כך:
    // ...
    // Add the Firebase products and methods that you want to use
    import {
      getFirestore,
      addDoc,
      collection,
      query,
      orderBy,
      onSnapshot,
      doc,
      setDoc,
      where
    } from 'firebase/firestore';
    
  3. בחלק התחתון של הפונקציה main(), מוסיפים את הקוד הבא כדי להאזין לסטטוס אישור ההגעה:
    async function main() {
      // ...
    
      // Listen to RSVP responses
      rsvpYes.onclick = async () => {
      };
      rsvpNo.onclick = async () => {
      };
    }
    main();
    
    
  4. לאחר מכן, יוצרים אוסף חדש בשם attendees ורושמים הפניה למסמך אם לוחצים על אחד מלחצני אישור ההשתתפות. מגדירים את ההפניה ל-true או ל-false בהתאם ללחצן שנלחץ.

    קודם כל, ל-rsvpYes:
    // ...
    // Listen to RSVP responses
    rsvpYes.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attendi()ng: true
      try {
        await setDoc(userRef, {
          attending: true
        });
      } catch (e) {
        console.error(e);
      }
    };
    
    ואז, אותו הדבר לגבי rsvpNo, אבל עם הערך false:
    rsvpNo.onclick = async () => {
      // Get a reference to the user's document in the attendees collection
      const userRef = doc(db, 'attendees', auth.currentUser.uid);
    
      // If they RSVP'd yes, save a document with attending: true
      try {
        await setDoc(userRef, {
          attending: false
        });
      } catch (e) {
        console.error(e);
      }
    };
    

עדכון כללי האבטחה

מכיוון שכבר הגדרתם כמה כללים, הנתונים החדשים שאתם מוסיפים באמצעות הלחצנים יידחו.

אפשר להוסיף פריטים לאוסף attendees

תצטרכו לעדכן את הכללים כדי לאפשר הוספה לאוסף attendees.

  1. במקרה של אוסף attendees, השתמשתם ב-UID של האימות כשם המסמך, ולכן אתם יכולים לאחזר אותו ולוודא ש-uid של השולח זהה למסמך שהוא כותב. תאפשרו לכולם לקרוא את רשימת המשתתפים (כי אין בה נתונים פרטיים), אבל רק יוצר האירוע יוכל לעדכן אותה.
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId;
        }
      }
    }
    
  2. לוחצים על פרסום כדי לפרוס את הכללים החדשים.

הוספת כללי אימות

  1. מוסיפים כמה כללים לאימות נתונים כדי לוודא שכל השדות הרצויים מופיעים במסמך:
    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        // ... //
        match /attendees/{userId} {
          allow read: if true;
          allow write: if request.auth.uid == userId
              && "attending" in request.resource.data;
    
        }
      }
    }
    
  2. אל תשכחו ללחוץ על פרסום כדי להפעיל את הכללים!

(אופציונלי) עכשיו אפשר לראות את התוצאות של הלחיצה על הלחצנים. נכנסים ללוח הבקרה של Cloud Firestore במסוף Firebase.

איך קוראים את סטטוס אישור ההשתתפות

עכשיו, אחרי שהקלטתם את התשובות, נראה מי מגיע ונעדכן את הממשק.

  1. ב-StackBlitz, עוברים לקובץ index.html.
  2. ב-description-container, מוסיפים רכיב חדש עם המזהה number-attending.
    <!-- ... -->
    
     <section id="description-container">
         <!-- ... -->
         <p id="number-attending"></p>
     </section>
    
    <!-- ... -->
    

לאחר מכן, רושמים את המאזין לאיסוף attendees וסופרים את מספר התשובות YES:

  1. ב-StackBlitz, עוברים לקובץ index.js.
  2. בחלק התחתון של הפונקציה main(), מוסיפים את הקוד הבא כדי להאזין לסטטוס אישור ההגעה ולספור את הלחיצות על YES.
    async function main() {
      // ...
    
      // Listen for attendee list
      const attendingQuery = query(
        collection(db, 'attendees'),
        where('attending', '==', true)
      );
      const unsubscribe = onSnapshot(attendingQuery, snap => {
        const newAttendeeCount = snap.docs.length;
        numberAttending.innerHTML = newAttendeeCount + ' people going';
      });
    }
    main();
    

לבסוף, נדגיש את הכפתור שמתאים לסטטוס הנוכחי.

  1. יוצרים פונקציה שבודקת אם ל-UID הנוכחי של האימות יש רשומה באוסף attendees, ואז מגדירים את המחלקה של הלחצן ל-clicked.
    // ...
    // Listen for attendee list
    function subscribeCurrentRSVP(user) {
      const ref = doc(db, 'attendees', user.uid);
      rsvpListener = onSnapshot(ref, doc => {
        if (doc && doc.data()) {
          const attendingResponse = doc.data().attending;
    
          // Update css classes for buttons
          if (attendingResponse) {
            rsvpYes.className = 'clicked';
            rsvpNo.className = '';
          } else {
            rsvpYes.className = '';
            rsvpNo.className = 'clicked';
          }
        }
      });
    }
    
  2. בנוסף, ניצור פונקציה לביטול ההרשמה. הערך הזה ישמש כשהמשתמש יתנתק.
    // ...
    function unsubscribeCurrentRSVP() {
      if (rsvpListener != null) {
        rsvpListener();
        rsvpListener = null;
      }
      rsvpYes.className = '';
      rsvpNo.className = '';
    }
    
  3. קוראים לפונקציות מתוך מאזין האימות.
    // ...
    // Listen to the current Auth state
      // Listen to the current Auth state
      onAuthStateChanged(auth, user => {
        if (user) {
          startRsvpButton.textContent = 'LOGOUT';
          // Show guestbook to logged-in users
          guestbookContainer.style.display = 'block';
    
          // Subscribe to the guestbook collection
          subscribeGuestbook();
          // Subscribe to the user's RSVP
          subscribeCurrentRSVP(user);
        } else {
          startRsvpButton.textContent = 'RSVP';
          // Hide guestbook for non-logged-in users
          guestbookContainer.style.display = 'none'
          ;
          // Unsubscribe from the guestbook collection
          unsubscribeGuestbook();
          // Unsubscribe from the guestbook collection
          unsubscribeCurrentRSVP();
        }
      });
    
  4. נסו להתחבר בתור כמה משתמשים ותראו שהמספר גדל עם כל קליק נוסף על הלחצן כן.

תצוגה מקדימה של האפליקציה

צילום מסך של השלב הזה

‫11. כל הכבוד!

השתמשתם ב-Firebase כדי לבנות אפליקציית אינטרנט אינטראקטיבית בזמן אמת.

מה למדנו

  • אימות ב-Firebase
  • FirebaseUI
  • Cloud Firestore
  • כללי אבטחה של Firebase

השלבים הבאים

  • רוצים לדעת עוד על תהליך העבודה למפתחים ב-Firebase? כדי ללמוד איך לבדוק את האפליקציה ולהריץ אותה באופן מקומי לחלוטין, אפשר לעיין בסדנת התכנות בנושא אמולטור Firebase.
  • רוצים לקבל מידע נוסף על מוצרים אחרים של Firebase? אולי אתם רוצים לאחסן קובצי תמונה שהמשתמשים מעלים? או לשלוח התראות למשתמשים? ב-Firebase web codelab יש מידע נוסף על מוצרי Firebase רבים לאינטרנט.
  • רוצים לקרוא מידע נוסף על Cloud Firestore? אולי תרצו לקרוא על אוספי משנה ועסקאות? ב-Cloud Firestore web codelab יש מדריך מפורט יותר בנושא Cloud Firestore. אפשר גם לצפות בסדרת הסרטונים הזו ב-YouTube כדי להכיר את Cloud Firestore.

מידע נוסף

איך היה?

נשמח לקבל משוב! ממלאים את הטופס הקצר כאן.