1. ספרייה
  2. HTTP והרשת
  3. פרוטוקולי ווב מודרניים

עודכן לפני חודש

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

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

זה לא היה רק שדרוג טכני. זה ייצג תשובה שונה מהיסוד לשאלה שכל API חייב לענות עליה: מי מחליט אילו נתונים עוברים על הקו?

ההבדל המהותי

REST אומר: השרת מחליט מה אתה מקבל.

GraphQL אומר: הלקוח מחליט מה הוא צריך.

כל הבדל אחר נובע מכך.

כיצד REST עובד

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

GET /users/123          → מחזיר את כל השדות שהשרת כולל
GET /users/123/posts    → מחזיר פוסטים עם כל השדות שלהם
GET /posts/456/comments → מחזיר תגובות עם כל השדות שלהן

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

זה השרת שמחליט. מחבר נקודת הקצה בחר מה לכלול. אתה מקבל את הבחירה שלו.

כיצד GraphQL עובד

GraphQL חושף נקודת קצה אחת. במקום לבקש משאבים לפי URL, אתה שולח שאילתה המתארת בדיוק את מה שאתה רוצה:

query {
  user(id: "123") {
    name
    email
    posts {
      title
      comments {
        text
        author {
          name
        }
      }
    }
  }
}

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

זה הלקוח שמחליט. אתה מגדיר את הצורה. השרת ממלא את המפרט שלך.

מדוע ההבדל הזה חשוב

בעיית רוחב הפס

בקש משתמש מ-REST API, ואולי תקבל 30 שדות כשאתה צריך 3. זה over-fetching — קבלת יותר נתונים מהנדרש. בחיבור מהיר במשרד, מי אכפת? ברשת סלולרית באינדונזיה הכפרית, זה ההבדל בין אפליקציה מגיבה לכזו שמשתמשים נוטשים.

GraphQL מבטל over-fetching בעיצובו. אתה מבקש שלושה שדות, אתה מקבל שלושה שדות.

בעיית מעגלי ההלוך-ושוב

הצג רכיב UI מורכב — נניח, לוח מחוונים עם פרטי משתמש, פעילות אחרונה, התראות והמלצות. עם REST, אולי תצטרך 5-10 בקשות נפרדות. כל בקשה מוסיפה השהייה. בחיבור עם זמן הלוך-ושוב של 200ms, זה 1-2 שניות של המתנה לפני שמשהו מתרנדר.

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

בעיית הגמישות

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

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

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

בעיית הגרסאות

שנה את מבנה נקודת קצה של REST, ואתה מסתכן בשבירת כל לקוח שמסתמך עליה. זה מוביל להתפשטות גרסאות — /v1/users, /v2/users, /v3/users — ולנטל התחזוקה של תמיכה בכולן.

GraphQL מטפל בהתפתחות באופן שונה. הוסף שדות חדשים בחופשיות — שאילתות קיימות לא נשברות כי הן לא מבקשות את השדות החדשים. הסר שדות ישנים על ידי סימונם כ-deprecated; הסכמה מתעדת זאת, ולקוחות יכולים לעבור בהדרגה. אין התפוצצות של גרסאות.

היכן GraphQL כואב

שמירה במטמון הופכת לקשה

REST רוכב על HTTP, ול-HTTP יש שמירה במטמון מובנית. GET /users/123 יכול להישמר במטמון על ידי דפדפנים, CDN ושרתי פרוקסי לפי ה-URL. אם לא השתנה דבר, המטמון מספק בקשות חוזרות באופן מיידי.

בקשות GraphQL הן בקשות POST ל-/graphql עם שאילתות בגוף הבקשה. שמירת המטמון הרגילה של HTTP לא חלה. אתה צריך אסטרטגיות מטמון מיוחדות — שאילתות מוחזקות, מטמון תגובות, מטמונים מנורמלים — שדורשות חשיבה ומימוש.

בעיית N+1

הנה תרחיש סיוט. לקוח שולח את השאילתה הזו:

query {
  posts {
    author {
      name
    }
  }
}

נראה תמים. אבל אם יש לך 100 פוסטים, מימוש נאיבי מביא את הפוסטים (שאילתה 1), ואז מביא כל מחבר בנפרד (100 שאילתות). זה 101 קריאות למסד הנתונים עבור שאילתת GraphQL אחת.

זו בעיית N+1, והיא תהרוס את מסד הנתונים שלך אם לא תפתור אותה. כלים כמו DataLoader מאגדים את הבקשות הללו, אבל הם דורשים הבנה ומימוש קפדני. תטעה, ושאילתת לקוח חכמה אחת תכניע את השרתים שלך.

המורכבות מצטברת

ניתן לבנות REST APIs עם כלים מינימליים. הגדר כמה נתיבים, החזר קצת JSON, גמרנו.

GraphQL דורש הגדרת סכמה, פונקציות resolver לכל שדה, מנוע הרצת שאילתות, והבנת מושגים כמו fragments, variables ו-directives. עקומת הלמידה היא אמיתית. המורכבות התפעולית גבוהה יותר.

הגבלת קצב הופכת למוזרה

עם REST, הגבלת קצב היא פשוטה: אפשר 100 בקשות ל-/users לשעה. פשוט.

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

היכן REST מצטיין

לפעמים הפשטות מנצחת

כתובות URL ממפות למשאבים. שיטות HTTP ממפות לפעולות. GET /users מביא משתמשים. POST /users יוצר אחד. המודל המנטלי מתאים למשפט אחד. מפתחים חדשים מבינים אותו מיד.

עבור APIs פשוטים — כמה משאבים, פעולות CRUD פשוטות — המנגנון של GraphQL הוא תקורה ללא תועלת.

שמירה במטמון פשוט עובדת

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

המערכת האקולוגית בשלה

REST קיים יותר משני עשורים. לכל שפה יש ספריות HTTP. כל כלי ניפוי שגיאות מטפל בו. כל מפתח השתמש בו. הבשלות הזו פירושה פחות הפתעות, יותר משאבים, גיוס קל יותר.

ל-APIs ציבוריים יש מוסכמות

מפתחים חיצוניים מצפים ל-REST. הם מכירים קודי סטטוס HTTP, content negotiation, דפוסי אימות סטנדרטיים. קיימות מוסכמות תיעוד. GraphQL מחייב אותם ללמוד משהו חדש — מכשול לאימוץ ה-API.

בחירה על סמך המציאות

GraphQL הגיוני כאשר:

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

REST הגיוני כאשר:

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

ניתן להשתמש בשניהם:

ארגונים רבים עושים זאת. REST ל-APIs ציבוריים וטיפול בקבצים. GraphQL לאפליקציות ניידות וכלים פנימיים מורכבים. הגישות אינן סותרות זו את זו.

שאלת פייסבוק

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

GraphQL פתר את הבעיה הספציפית הזו. הוא מאפשר ללקוחות לבקש בדיוק את מה שהם צריכים בבקשה אחת. עבור המקרה של פייסבוק — נתונים חברתיים מורכבים, mobile-first, הרבה לקוחות שונים — זו הייתה התשובה הנכונה.

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

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

שאלות נפוצות על GraphQL מול REST

האם ניתן לעבור מ-REST ל-GraphQL בהדרגה?

כן. הוסף נקודת קצה GraphQL לצד ה-REST API הקיים שלך. העבר לקוחות אחד בכל פעם, תחל מאלה שנהנים ממנו ביותר (אפליקציות ניידות, לוחות מחוונים מורכבים). שמור REST ללקוחות שבהם הוא עובד היטב. אין דרישה לבחור אחד בלעדי.

מה מהיר יותר, GraphQL או REST?

לא אחד מהם, מטבעו. GraphQL יכול להיות מהיר יותר (פחות הלוך-ושוב, פחות העברת נתונים) או איטי יותר (בעיות N+1, אין מטמון HTTP). REST יכול להיות מהיר יותר (מטמון אגרסיבי, שאילתות פשוטות) או איטי יותר (הלוך-ושוב מרובים, over-fetching). הביצועים תלויים באיכות המימוש ובהתאמה למקרה השימוש.

האם GraphQL מחליף את REST?

לא. הם פותרים בעיות שונות היטב. GraphQL מצטיין בשליפת נתונים גמישה ללקוחות מגוונים. REST מצטיין ב-APIs פשוטים, ניתנים למטמון, המכוונים למשאבים. ארגונים רבים משתמשים בשניהם.

כיצד מטפלים באימות עם GraphQL?

באותו אופן שהיית עושה עם REST — טוקנים בכותרות, עוגיות, או מנגנונים דומים. GraphQL לא מגדיר אימות; זה קורה בשכבת ה-HTTP לפני שהשרת GraphQL מעבד שאילתות.

מה לגבי נתונים בזמן אמת?

GraphQL תומך ב-subscriptions לעדכונים בזמן אמת, אם כי מורכבות המימוש משתנה. REST בדרך כלל משתמש ב-WebSockets או Server-Sent Events לתכונות בזמן אמת. לא אחת מהגישות עדיפה מטבעה לזמן אמת; שתיהן דורשות תשתית נוספת.

האם דף זה היה מועיל?

😔
🤨
😃