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

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

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

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

מה תלמדו

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

מה צריך להכין

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

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

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

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

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

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

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

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

חומרי ההתחלה של סדנת הקוד הזו מספקים מבנה מסוים לאפליקציית האינטרנט, כולל כמה גיליונות סגנונות וכמה קונטיינרים של HTML לאפליקציה. בהמשך סדנת הקוד הזו, תקשרו את הקונטיינרים האלה ל-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.
  2. במסוף Firebase, לוחצים על Add Project (הוספת פרויקט) (או על Create a project (יצירת פרויקט)), נותנים שם לפרויקט ב-Firebase – Firebase-Web-Codelab.

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

  3. לוחצים על האפשרויות ליצירת פרויקט. מאשרים את התנאים של Firebase, אם מופיעה בקשה. במסך של Google Analytics, לוחצים על 'לא להפעיל' כי לא תשתמשו ב-Analytics באפליקציה הזו.

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

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

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

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

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

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

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

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

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

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

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

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

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

הגדרת Cloud Firestore

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

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

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

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

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

מוסיפים את ספריות Firebase

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

ב-StackBlitz יש קיבוץ אוטומטי, כך שאפשר להוסיף את ספריות Firebase באמצעות הצהרות ייבוא. תשתמשו בגרסאות המודולריות (v9) של הספריות, שבעזרתן אפשר לצמצם את הגודל הכולל של דף האינטרנט באמצעות תהליך שנקרא 'ניפוי עצים'. מידע נוסף על ערכות ה-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, עוברים לדף הסקירה הכללית של הפרויקט בלחיצה על סקירה כללית של הפרויקט בפינה הימנית העליונה.
  2. במרכז דף הסקירה הכללית של הפרויקט, לוחצים על סמל האינטרנט סמל של אפליקציה לאינטרנט כדי ליצור אפליקציית אינטרנט חדשה ב-Firebase.

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

  3. רושמים את האפליקציה בכינוי Web App.
  4. לצורך ה-Codelab הזה, אין לסמן את התיבה לצד האפשרות אני רוצה להגדיר גם אירוח ב-Firebase לאפליקציה הזו. בינתיים תשתמשו בחלונית התצוגה המקדימה של StackBlitz.
  5. לוחצים על רישום האפליקציה.

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

  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. הוספת פרטי כניסה של משתמש (RSVP)

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

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

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

כדי להשתמש בממשק המשתמש של FirebaseUI, יש להגדיר שתי פעולות אפשריות (ראו אפשרויות במסמכי התיעוד):

  • הקוד הזה מורה ל-FirebaseUI להשתמש בשיטת הכניסה כתובת אימייל/סיסמה.
  • הפונקציה מטפלת בקריאה החוזרת (callback) לכניסה מוצלחת ומחזירה את הערך 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 כמו שמתואר בהמשך, כי ל-Codelab הזה כבר יש קטעי הוק (hooks) למזהים הספציפיים האלה בקובץ index.js.

    שימו לב שבקובץ 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. מגדירים את ה-listener בלחצן לאישור השתתפות (RSVP) ומפעילים את פונקציית ההתחלה של 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, לחצו על הלחצן 'אישור השתתפות' כדי להיכנס לאפליקציה.
    • בקודלאב הזה אפשר להשתמש בכל כתובת אימייל, גם כתובת אימייל מזויפת, כי לא מגדירים שלב אימות אימייל בקודלאב הזה.
    • אם מופיעה הודעת השגיאה 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 במרכז הבקרה, אתם אמורים לראות את האוסף 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 מסנכרן נתונים באופן אוטומטי ומיידי עם לקוחות שנרשמו למסד הנתונים.

  • ההודעות שיצרתם מקודם במסד הנתונים אמורות להופיע באפליקציה. אתם יכולים לכתוב הודעות חדשות, והן אמורות להופיע באופן מיידי.
  • אם פותחים את סביבת העבודה בכמה חלונות או כרטיסיות, ההודעות מסונכרנות בזמן אמת בין הכרטיסיות.
  • (אופציונלי) אפשר לנסות למחוק, לשנות או להוסיף הודעות חדשות באופן ידני ישירות בקטע מסד נתונים במסוף 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.
      }
    }
    

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

מאחר שהשתמשתם במזהה האימות (Authentication 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 של ספר האורחים ל-Authentication listener. אחרת, שגיאות שקשורות להרשאות יקרו והאפליקציה תנותק כשהמשתמש יתנתק מהחשבון.

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

    אוזן ה-Firestore onSnapshot מחזיר פונקציית ביטול הרשמה שתהיה לך אפשרות להשתמש בה כדי לבטל את האזנה בתמונת המצב מאוחר יותר.
    // ...
    // 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, ואז קוראים לפונקציה כדי לבטל את המאזין.
    // ...
    // Unsubscribe from guestbook updates
    function unsubscribeGuestbook() {
      if (guestbookListener != null) {
        guestbookListener();
        guestbookListener = null;
      }
    }
    

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

  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, מכיוון שהשתמשת ב-Authentication 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(), מוסיפים את הקוד הבא כדי להאזין לסטטוס המענה ולהספיד את הקליקים על כן.
    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? בCodelab של אמולטור Firebase מוסבר איך לבדוק ולהפעיל את האפליקציה באופן מקומי לחלוטין.
  • רוצים לקבל מידע נוסף על מוצרים אחרים של Firebase? אולי אתם רוצים לאחסן קובצי תמונה שהמשתמשים מעלים? או לשלוח התראות למשתמשים? ב-Firebase באינטרנט Codelab אפשר למצוא מעבדת Codelab מפורטת יותר על הרבה מוצרים נוספים של Firebase לאינטרנט.
  • רוצים לקבל מידע נוסף על Cloud Firestore? רוצה לקבל מידע נוסף על עסקאות ואוספים של אוספים? בcodelab בנושא Cloud Firestore לאינטרנט מוסבר בהרחבה על Cloud Firestore. אפשר גם לעיין בסדרת YouTube הזו כדי להכיר את Cloud Firestore!

מידע נוסף

איך היה?

נשמח לקבל ממך משוב. עליך למלא טופס קצר (מאוד) כאן.