תארו לעצמכם: ה-frontend שלכם דורש נתונים עם קינון מותאם אישית — מאמרים עם מחברים, קטגוריות, תגיות ואזורים דינמיים. ללא הגדרת API נכונה, אתם מקבלים שאילתות N+1, תגובות JSON ענקיות והאטה ב-LCP. לדוגמה, בקשה טיפוסית למאמר עם מחבר וקטגוריה ללא אופטימיזציה מייצרת 4 שאילתות מסד נתונים, ומגדילה את ה-TTFB ל-2 שניות. לאחר אופטימיזציה, מדובר בשאילתה אחת ו-TTFB של 200 אלפיות השנייה — הפחתה של 90%. אופטימיזציה כזו ביצענו עבור 30+ פרויקטים במשך 6 שנים, באמצעות מתודולוגיה מוכחת. במדריך זה, נפרק כיצד להגדיר REST ו-GraphQL ב-Strapi, להימנע מטעויות נפוצות ולהאיץ את ה-API עד פי 10.
למה להשתמש ב-REST ו-GraphQL יחד?
ה-REST API ב-Strapi עובד ישירות מהקופסה — מושלם לרשימות פשוטות ו-CRUD סטנדרטי. GraphQL דרך הפלאגין מתחבר תוך 5 דקות ופותר את בעיית ה-overfetching. GraphQL מפחית את נפח העברת הנתונים בעד 80% בהשוואה ל-REST עבור היררכיות מורכבות — כך מאשרת הפרקטיקה שלנו. אנו משלבים אותם: REST עבור נקודות קצה ציבוריות, GraphQL עבור פאנל הניהול וכלים פנימיים. השוואת יכולות מופיעה בטבלה.
| קריטריון | REST API | GraphQL API |
|---|---|---|
| מוכנות | מיד לאחר ההשקה | דורש התקנת פלאגין |
| בקשות | בקשות מרובות עבור קשרים | בקשה אחת עם אובייקטים מקוננים |
| שמירה במטמון | מטמון HTTP (ETag, CDN) | מורכב יותר (דורש שאילתות מתמשכות) |
| גמישות | מבנה תגובה קבוע | הלקוח בוחר שדות |
| ביצועים | קל יותר לאופטימיזציה דרך מסד הנתונים | סיכון לקינון עמוק ו-N+1 |
איך להגדיר REST API?
פורמט התגובה של Strapi אחיד:
{
"data": {
"id": 1,
"attributes": {
"title": "Article",
"slug": "article",
"publishedAt": "..."
}
},
"meta": {}
}לסינון, populate, פגינציה ומיון, השתמשו בפרמטרים של שאילתה. דוגמה לבקשה עם כל התכונות:
GET /api/articles?filters[status][$eq]=published&filters[price][$gte]=100&populate=author,category&sort[0]=publishedAt:desc&pagination[page]=2&pagination[pageSize]=10&fields[0]=title,slug אופרטורים נתמכים: $eq, $ne, $lt, $in, $contains, $startsWith, $endsWith, $null, $notNull והגרסאות הרגישות לאותיות רישיות עם הסיומת i. עבור קשרים השתמשו ב-populate — הוא יכול להיות עמוק, אך הגבילו את העומק באמצעות ה-middleware strapi::populate-depth (מומלץ maxDepth: 3) כדי להימנע מ-N+1.
איך לחבר ולהתאים את GraphQL?
התקינו את הפלאגין @strapi/plugin-graphql והוסיפו הגדרות ב-config/plugins.js (endpoint, מגבלות, השבתת playground בסביבת production). דוגמה לשאילתת GraphQL לשליפת מאמרים עם נתונים מקוננים:
query GetArticles($locale: I18NLocaleCode, $page: Int) {
articles(
locale: $locale
pagination: { page: $page, pageSize: 10 }
sort: "publishedAt:desc"
filters: { publishedAt: { notNull: true } }
) {
data {
id
attributes {
title
slug
excerpt
publishedAt
cover {
data {
attributes {
url
alternativeText
}
}
}
category {
data {
attributes {
name
slug
}
}
}
}
}
meta {
pagination {
total
pageCount
}
}
}
}עבור resolvers מותאמים אישית, השתמשו ב-extensionService. צרו שדה featuredArticles המחזיר רק מאמרים מומלצים:
// src/index.ts
export default {
register({ strapi }) {
const extensionService = strapi.plugin('graphql').service('extension')
extensionService.use(({ nexus }) => ({
types: [
nexus.extendType({
type: 'Query',
definition(t) {
t.field('featuredArticles', {
type: 'ArticleEntityResponseCollection',
resolve: async (_root, _args, context) => {
const articles = await strapi.entityService.findMany(
'api::article.article',
{
filters: { featured: true },
populate: ['cover', 'category'],
sort: { publishedAt: 'desc' },
limit: 6,
}
)
return { data: articles }
},
})
},
}),
],
}))
},
}
איך לשפר את ביצועי ה-API?
שמרו שאילתות כבדות במטמון עם Redis. לדוגמה, עבור featuredArticles:
const redis = new Redis(process.env.REDIS_URL)
const cachedFeatured = await redis.get('featured-articles')
if (cachedFeatured) return JSON.parse(cachedFeatured)
const articles = await strapi.entityService.findMany(...)
await redis.setex('featured-articles', 300, JSON.stringify(articles))טעות נפוצה היא שאילתות N+1 עם populate אגרסיבי. אם אתם משתמשים ב-populate=*, Strapi מבצע שאילתות מסד נתונים נפרדות עבור כל קשר. הגבלת עומק באמצעות ה-middleware strapi::populate-depth ושמירה במטמון Redis פותרים בעיה זו. Strapi GraphQL מכוון היטב יכול להיות מהיר משמעותית מ-REST עבור שאילתות מורכבות עם קשרים רבים.
בנוסף, השתמשו ב-Varnish או CDN לשמירת תגובות של נקודות קצה ציבוריות במטמון. השוואת אסטרטגיות שמירה במטמון מופיעה בטבלה השנייה.
| אסטרטגיה | מתי להשתמש | רווח במהירות |
|---|---|---|
| Redis | נתונים דינמיים, עדכונים תכופים | מפחית עומס על מסד הנתונים פי 5–10 |
| Varnish | נקודות קצה ציבוריות, משתנות לעיתים רחוקות | זמן תגובה עד 50 אלפיות השנייה |
| CDN | נכסים סטטיים (תמונות, קבצים) | קרבה למשתמש, הפחתת TTFB |
תוכנית שלב אחר שלב לאופטימיזציה של Strapi API
- נתחו בקשות נוכחיות. השתמשו ב-logger המובנה של Strapi או בכלים חיצוניים (Kibana) לזיהוי נקודות קצה איטיות.
- הגדירו populate-depth. הוסיפו את ה-middleware strapi::populate-depth עם maxDepth: 3 בהגדרות.
- יישמו שמירה במטמון עם Strapi Redis. שמרו תוצאות של שאילתות כבדות עם TTL של 300 שניות — זה מפחית עומס על מסד הנתונים עד פי 10.
- עברו ל-GraphQL עבור קשרים מורכבים. אם ה-frontend מבקש נתונים מקוננים, השתמשו ב-GraphQL — הוא מפחית נתונים מועברים עד 80%.
- נטרו וחזרו על התהליך. בדקו ביצועים באופן קבוע דרך יומני הביקורת של Strapi והתאימו הגדרות.
מה כלול בהקמת API סוהר?
- הגדרת REST ו/או GraphQL תוך התחשבות בעומס;
- resolvers ו-middleware מותאמים אישית;
- אופטימיזציה של populate ושמירה במטמון (Redis, Varnish);
- הגדרת הרשאות גישה ותפקידים;
- תיעוד (אוסף Postman, תיאור נקודות קצה);
- הדרכת צוות (1–2 מפגשים);
- שבועיים של תמיכה לאחר המסירה.
לוח זמנים
הגדרת הפלאגין Strapi GraphQL, resolvers מותאמים אישית ואופטימיזציה של שאילתות אורכת בין 2 ל-5 ימים. המחיר מתחיל ב-$1,500 — שלחו לנו בריף ונספק הערכה מפורטת. שמירה נכונה במטמון יכולה להפחית עלויות שרת עד 40%, והחיסכון הממוצע בתקציב התשתית עבור הלקוחות שלנו הוא 30%. שיפור הביצועים המובטח שלנו כולל הפחתת TTFB ב-90%. קבעו פגישת ייעוץ כדי לדון בפרטי ה-API שלכם. צרו קשר.
מקור: תיעוד רשמי של Strapi על GraphQL — https://docs.strapi.io/dev-docs/plugins/graphql







