שדרוג מ-API במרחב שמות לאפליקציה מודולרית

באפליקציות שמשתמשות ב-Firebase Web API עם מרחבי שמות, החל מספריות compat ועד לגרסה 8 ואילך, מומלץ לעבור ל-API המודולרי לפי ההוראות במדריך הזה.

במדריך הזה נניח שאתם מכירים את ממשק ה-API שמוגדר למרחב שמות, ושאתם מתכוונים להשתמש ב-bundler של מודולים כמו webpack או Rollup כדי לשדרג את האפליקציה ולפתח אותה באופן שוטף.

מומלץ מאוד להשתמש ב-bundler של מודולים בסביבת הפיתוח. אם לא תשתמשו באחד מהם, לא תוכלו ליהנות מהיתרונות העיקריים של ה-API המודולרי, שהם צמצום גודל האפליקציה. כדי להתקין את ה-SDK, תצטרכו את npm או את yarn.

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

מידע על ספריות עם מרחב שמות (compat)

יש שני סוגים של ספריות ל-Firebase Web SDK:

  • מודולרי – ממשק API חדש שמיועד להסרת קוד שלא בשימוש (tree-shaking) כדי להפוך את אפליקציית האינטרנט לקטנה ומהירה ככל האפשר.
  • מרחב שמות (compat) – ממשק API מוכר שתואם באופן מלא לגרסאות הקודמות של ה-SDK, ומאפשר לשדרג בלי לשנות את כל הקוד של Firebase בבת אחת. לספריות התאימות יש מעט יתרונות בגודל או בביצועים בהשוואה לספריות המקבילות עם מרחב השמות.

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

באפליקציות עם חשיפה קטנה מאוד ל-Firebase Web SDK – לדוגמה, אפליקציה שמבצעת רק קריאה פשוטה ל-API‏ Authentication – יכול להיות שיהיה שימושי לבצע רפאקציה של קוד ישן יותר שמוגדר במרחב שמות בלי להשתמש בספריות התאימות. אם אתם משדרגים אפליקציה כזו, תוכלו לפעול לפי ההוראות במדריך הזה לגבי 'ה-API המודולרי' בלי להשתמש בספריות התאימות.

מידע על תהליך השדרוג

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

  1. מוסיפים את הספריות המודולריות ואת ספריות התאימות לאפליקציה.
  2. מעדכנים את הצהרות הייבוא בקוד ל-compat.
  3. שינוי הקוד של מוצר יחיד (לדוגמה, Authentication) לסגנון מודולרי.
  4. אופציונלי: בשלב הזה, מסירים את ספריית התאימות Authentication ואת קוד התאימות של Authentication כדי לממש את היתרונות של התאמת הגודל לאפליקציה Authentication לפני שממשיכים.
  5. מבצעים פונקציות של כל מוצר (לדוגמה, Cloud Firestore,‏ FCM וכו') בסגנון מודולרי, מבצעים הידור ובדיקה עד שכל האזורים הושלמו.
  6. מעדכנים את קוד האתחול לסגנון המודולרי.
  7. מסירים מהאפליקציה את כל הצהרות התאימות ואת קוד התאימות שנותרו.

הורדת הגרסה האחרונה של ה-SDK

כדי להתחיל, צריך לקבל את הספריות המודולריות ואת ספריות התאימות באמצעות npm:

npm i firebase@11.3.0

# OR

yarn add firebase@11.3.0

עדכון ייבוא לצורך תאימות

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

לפני: גרסה 8 ואילך

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

אחרי: compat

// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

שינוי מבנה הקוד לסגנון מודולרי

ממשקי ה-API עם מרחב השמות מבוססים על תבנית שירות ומרחב שמות עם שרשור נקודות, אבל הגישה המודולרית מאפשרת לארגן את הקוד בעיקר סביב פונקציות. ב-API המודולרי, החבילה firebase/app וחבילות אחרות לא מחזירות ייצוא מקיף שמכיל את כל השיטות מהחבילה. במקום זאת, החבילות מייצאות פונקציות בודדות.

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

דוגמה 1: עיצוב מחדש של פונקציית Authentication

לפני: compat

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

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

אחרי: מודולרי

הפונקציה getAuth מקבלת את firebaseApp כפרמטר הראשון שלה. הפונקציה onAuthStateChanged לא מקושרת למכונה auth כמו שהיא מקושרת ב-API שמוגדר למרחב שמות. במקום זאת, היא פונקציה חופשית שמקבלת את auth כפרמטר הראשון שלה.

import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
  // Check for user status
});

עדכון הטיפול בשיטת האימות getRedirectResult

ב-API המודולרי יש שינוי שפוגע בתאימות ב-getRedirectResult. כשלא מתבצעת קריאה לפעולה של הפניה אוטומטית, ממשק ה-API המודולרי מחזיר את הערך null, בניגוד לממשק ה-API עם מרחבי השמות, שהחזיר את הערך UserCredential עם משתמש null.

לפני: compat

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

אחרי: מודולרי

const result = await getRedirectResult(auth);
// Provider of the access token could be Facebook, Github, etc.
if (result === null || provider.credentialFromResult(result) === null) {
  return null;
}
return result;

דוגמה 2: שינוי מבנה של פונקציית Cloud Firestore

לפני: compat

import "firebase/compat/firestore"

const db = firebase.firestore();
db.collection("cities").where("capital", "==", true)
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

אחרי: מודולרי

הפונקציה getFirestore מקבלת את firebaseApp בתור הפרמטר הראשון שלה, שהוחזר מ-initializeApp בדוגמה הקודמת. שימו לב שהקוד ליצירת שאילתה שונה מאוד ב-API המודולרי. אין שרשור, ושיטות כמו query או where מוצגות עכשיו כפונקציות חופשיות.

import { getFirestore, collection, query, where, getDocs } from "firebase/firestore";

const db = getFirestore(firebaseApp);

const q = query(collection(db, "cities"), where("capital", "==", true));

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

עדכון ההפניות ל-Firestore DocumentSnapshot.exists

ב-API המודולרי יש שינוי שגורם לשבירה של תאימות, שבו המאפיין firestore.DocumentSnapshot.exists השתנה לשיטה. הפונקציונליות היא בעיקרה זהה (בדיקה אם מסמך קיים), אבל צריך לבצע רפאקציה של הקוד כדי להשתמש בשיטה החדשה, כפי שמוצג:

Before:compat

if (snapshot.exists) {
  console.log("the document exists");
}

אחרי: מודולרי

if (snapshot.exists()) {
  console.log("the document exists");
}

דוגמה 3: שילוב של סגנונות קוד עם מרחב שמות וקוד מודולרי

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

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'

const docRef = firebase.firestore().doc();
getDoc(docRef);

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

עדכון קוד האתחול

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

לפני: compat

import firebase from "firebase/compat/app"

firebase.initializeApp({ /* config */ });

אחרי: מודולרי

import { initializeApp } from "firebase/app"

const firebaseApp = initializeApp({ /* config */ });

הסרת קוד התאימות

כדי ליהנות מהיתרונות של ה-API המודולרי מבחינת הגודל, צריך בסופו של דבר להמיר את כל ההפעלות לסגנון המודולרי שמוצג למעלה ולהסיר מהקוד את כל ההצהרות מסוג import "firebase/compat/*. בסיום, לא אמורות להיות יותר הפניות למרחב השמות הגלובלי firebase.* או לקוד אחר בסגנון API עם מרחב שמות.

שימוש בספריית ה-compat מהחלון

ה-API המודולרי מותאם לעבודה עם מודולים ולא עם האובייקט window של הדפדפן. בגרסאות קודמות של הספרייה אפשר היה לטעון ולנהל את Firebase באמצעות מרחב השמות window.firebase. לא מומלץ להשתמש באפשרות הזו בעתיד, כי היא לא מאפשרת להסיר קוד שלא בשימוש. עם זאת, גרסת התאימות של ה-SDK ל-JavaScript פועלת עם window למפתחים שלא רוצים להתחיל מיד את תהליך השדרוג המודולרי.

<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/11.3.0/firebase-auth-compat.js"></script>
<script>
   const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
   const db = firebaseApp.firestore();
   const auth = firebaseApp.auth();
</script>

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

היתרונות והמגבלות של ה-SDK המודולרי

ל-SDK המורכב ממודולים יש יתרונות אלה על פני גרסאות קודמות:

  • ה-SDK המודולרי מאפשר להקטין באופן משמעותי את גודל האפליקציה. הוא מבוסס על פורמט המודולים המודרני של JavaScript, שמאפשר שיטות של 'ניפוי עצים' שבהן מייבאים רק את הארטיפקטים הנחוצים לאפליקציה. בהתאם לאפליקציה שלכם, שימוש ב-tree-shaking עם ה-SDK המודולרי יכול להוביל לקיצור של 80% בקיבוביות (KB) בהשוואה לאפליקציה דומה שנוצרה באמצעות ה-API במרחב השמות.
  • ערכת ה-SDK המודולרית תמשיך ליהנות מפיתוח מתמשך של תכונות, ואילו ה-API במרחב השמות לא ייהנה מכך.