מצב טיפוסי: מעצב יצר קטלוג עם פילטרים מונפשים, עדכוני סל מיידיים ומעברי עמוד ללא טעינה מחדש. מפתח הפרונטאנד מסתכל על תבניות bitrix:catalog.section ו-bitrix:sale.order.ajax ומבין שהתאמתן למודל הקומפוננטות הסטנדרטי של ביטריקס בלתי אפשרית ללא פתרונות מאולתרים. כאן נכנסת הגישה ה-headless: ביטריקס נשארת השרת האחורי, וכל הממשק חי על Vue.js. זה לא סטאק אופנתי לשם האופנה. Headless מוצדק כשתבניות ביטריקס הסטנדרטיות לא יכולות לספק את חוויית המשתמש הנדרשת, כשצוות הפרונטאנד עובד באופן עצמאי ממפתחי השרת האחורי, או כשאפשרות API אחת משרתת את האתר, אפליקציית המובייל והקיוסקים במיקומים לא מקוונים. אנו משתמשים בגישה זו כבר למעלה מ-5 שנים ויישמנו יותר מ-20 פרויקטים — מקטלוגים קטנים ועד פורטלי B2B עם עשרות אלפי מוצרים. הניסיון מראה שעם ארכיטקטורה נכונה, headless מספק חוויית משתמש מודרנית וביצועים גבוהים, עם אחריות של 12 חודשים על העבודה.
למה headless על ביטריקס הוא פתרון מוצדק?
לפרויקטים שבהם ממשק ביטריקס הסטנדרטי לא עומד בדרישות לאנימציה, מהירות מעבר, או הצורך לעבוד במכשירים ניידים עם JavaScript מושבת (SSR). Headless גם מאפשר הפרדת צוותים: מפתחי פרונטאנד עובדים עם Vue, השרת האחורי עם ביטריקס, והחוזה ביניהם הוא מפרט API. בנוסף, גישה זו סוללת את הדרך באופן טבעי לריבוי-פלטפורמות — API אחד משרת את האתר, האפליקציה והקיוסקים. ההחזר על ההשקעה ב-headless הוא כ-6–12 חודשים, הודות להפחתה של עד 30% בעלויות תחזוקת הפרונטאנד.
ארכיטקטורה: איך שכבות מופרדות
בחנות ביטריקס קלאסית, קומפוננטת PHP מביאה נתונים, מעבירה מערך ל-template.php, שבו כלולים גם CSS ו-JS. בסכימת ה-headless, הכל שונה:
- ביטריקס פועלת כשרת API. קטלוג, מחירים, מלאי, סל, תשלום, הרשאה — הכל דרך REST API (מודול
rest) או קונטרולרים מותאמים אישית המבוססים על\Bitrix\Main\Engine\Controller. - Vue.js / Nuxt.js — אפליקציה נפרדת. מציגה את הממשק, מנהלת ניתוב, מצב, טפסים.
- Nginx מנתב:
/api/*הולך לביטריקס, השאר הולך ל-Vue סטטי או ל-Node.js (עם SSR).
פריסות הפרונטאנד והשרת האחורי עצמאיות. מפתח הפרונטאנד דוחף לריפוזיטורי שלו, CI בונה את ה-bundle, פורס ל-CDN או לשרת Node. השרת האחורי מעדכן את ביטריקס בנפרד. החוזה ביניהם הוא מפרט ה-API.
| פרמטר | ביטריקס קלאסית | Headless (Vue + ביטריקס) |
|---|---|---|
| עיבוד | צד שרת (PHP) | צד לקוח + CSR/SSR |
| קאשינג | קאש מרוכב | ISR, CDN, Service Worker |
| פיתוח | קשור לתבניות | עצמאי |
| אינדוקס | מובנה | דורש SSR |
| גמישות ממשק | מוגבל על ידי קומפוננטות | מקסימלית |
Bitrix REST API: מה עובד ומה צריך להשלים
המודול rest מספק שיטות לישויות החנות הראשיות:
-
catalog.product.list— מוצרים עם סינון לפי מאפיינים, סעיפים, מחירים -
catalog.product.get— כרטיס מפורט -
catalog.product.offer.list— הצעות מסחר (SKU) -
catalog.section.list— עץ קטגוריות -
catalog.price.list— מחירים לפי סוג -
sale.basket.addItem,sale.basket.updateItem,sale.basket.deleteItem,sale.basket.getItems -
sale.order.add,sale.order.get,sale.order.list -
sale.shipment.getDeliveryServices,sale.paySystem.getList
על הנייר, הכל מכוסה. בפועל, מופיעים ניואנסים. catalog.product.list לא מחזיר מאפיינים שרירותיים של בלוק מידע. צריך לבקש בנוסף דרך catalog.product.getFieldsByFilter או לכתוב נקודת קצה משלך. סינון פאקטלי — ספירת מספר המוצרים עבור כל ערך פילטר, כמו ב-smart_filter הסטנדרטי — חסר ב-REST API. חישוב עלות משלוח בהתבסס על תוכן הסל הוא שיטה נוספת שחסרה כברירת מחדל.
הפתרון הוא שיטות REST מותאמות אישית. הן נרשמות דרך \CRestServer::onRestServiceBuildDescription() או דרך \Bitrix\Main\Engine\Controller עם האנוטציה @restMethod. בצד ביטריקס, הקונטרולר המותאם אישית מבצע את השאילתה ומחזיר JSON:
-
/api/catalog/filter— מוצרים + פאקטות (ספירות לכל ערך פילטר) -
/api/cart/calculate— חישוב מחדש של הסל תוך התחשבות בכללי סל, הנחות וקודי קופון -
/api/checkout/submit— תשלום בבקשה אחת
אינדקס הפאקטות הוא סיפור נפרד. ביטריקס מאחסנת פאקטות מחושבות מראש בטבלת b_catalog_smart_filter. בגישת headless, או שמשתמשים בטבלה זו ישירות דרך ORM או שבונים פאקטות תוך כדי תנועה. האפשרות הראשונה מהירה יותר אבל קושרת אותך למבנה הפנימי של ביטריקס. השנייה איטית יותר בקטלוגים גדולים (50,000+ מוצרים) אבל צפויה. לפי ויקיפדיה, REST הוא סגנון ארכיטקטוני לאינטראקציה בין רכיבים של אפליקציה מבוזרת דרך רשת.
פרטים טכניים למפתחים בכירים
לאופטימיזציה של קטלוגים גדולים, מומלץ להשתמש ב-HL blocks לאחסון מאפיינים נוספים וקאש מתויג. לדוגמה, בעדכון מחיר מוצר דרך סוכן, אפשר לפסול רק את הקאש המתויג מבלי להשפיע על עמודים אחרים. סוכנים ואירועים (`OnAdminListDisplay`, `OnSaleOrderSaved`) עוזרים לסנכרן נתונים בין ביטריקס לשירותים חיצוניים כמו CDEK או YooKassa.ארכיטקטורת קומפוננטות של אפליקציית Vue
מבנה הפרונטאנד לחנות מקוונת:
src/
├── pages/
│ ├── CatalogPage.vue # список товаров с фильтрами
│ ├── ProductPage.vue # карточка товара
│ ├── CartPage.vue # корзина
│ ├── CheckoutPage.vue # оформление
│ └── AccountPage.vue # личный кабинет
├── components/
│ ├── catalog/
│ │ ├── ProductCard.vue
│ │ ├── FilterPanel.vue
│ │ └── FacetCounter.vue
│ ├── cart/
│ │ ├── CartItem.vue
│ │ └── CartSummary.vue
│ └── ui/ # переиспользуемые элементы
├── stores/
│ ├── catalogStore.ts # Pinia: товары, фильтры, пагинация
│ ├── cartStore.ts # корзина, синхронизация с API
│ ├── userStore.ts # авторизация, токен
│ └── checkoutStore.ts # оформление заказа
├── api/
│ ├── catalog.ts # обёртки над API каталога
│ ├── cart.ts
│ └── auth.ts
└── composables/
├── useProductFilter.ts # логика фильтрации
└── useInfiniteScroll.ts # бесконечная прокрутка
Pinia מנהלת את המצב. src/ ├── pages/ │ ├── CatalogPage.vue # список товаров с фильтрами │ ├── ProductPage.vue # карточка товара │ ├── CartPage.vue # корзина │ ├── CheckoutPage.vue # оформление │ └── AccountPage.vue # личный кабинет ├── components/ │ ├── catalog/ │ │ ├── ProductCard.vue │ │ ├── FilterPanel.vue │ │ └── FacetCounter.vue │ ├── cart/ │ │ ├── CartItem.vue │ │ └── CartSummary.vue │ └── ui/ # переиспользуемые элементы ├── stores/ │ ├── catalogStore.ts # Pinia: товары, фильтры, пагинация │ ├── cartStore.ts # корзина, синхронизация с API │ ├── userStore.ts # авторизация, токен │ └── checkoutStore.ts # оформление заказа ├── api/ │ ├── catalog.ts # обёртки над API каталога │ ├── cart.ts │ └── auth.ts └── composables/ ├── useProductFilter.ts # логика фильтрации └── useInfiniteScroll.ts # бесконечная прокрутка הוא הכי לא טריוויאלי: בהוספת מוצר, צריך לעדכן את הממשק באופן מיידי (עדכון אופטימי), לשלוח בקשה ל-API, לקבל תשובה עם המחיר בפועל (ביטריקס אולי החילה הנחה או ניכתה מלאי) ולסנכרן את המצב המקומי עם השרת. למשתמשים לא מורשים, הסל חי ב-cartStore ועובר לשרת לאחר התחברות. Vue Router עם טעינה עצלה: כל עמוד הוא chunk נפרד. מעברים בין קטגוריות לא טוענים מחדש את האפליקציה, ופילטרים נכתבים לפרמטרי URL לקישורים ניתנים לשיתוף.
איך להגדיר SSR לאינדוקס?
אפליקציית Vue SPA מציגה בצד הלקוח. בוט חיפוש רואה localStorage ריק. לחנות מקוונת שבה כרטיסי מוצר וקטגוריות חייבים להיות באינדוקס, זה גזר דין מוות.
Nuxt.js עם SSR הוא האפשרות העיקרית. שרת Node.js מציג קומפוננטות Vue ל-HTML; נתונים מ-API של ביטריקס נמשכים דרך <div id="app"></div> או useFetch(). הלקוח מקבל HTML מוכן; לאחר הידרציה, האפליקציה עובדת כ-SPA. שימוש ב-SSR מפחית את זמן הציור הראשון ב-40–60%.
Nuxt.js עם ISR (Incremental Static Regeneration) הוא גישה היברידית. עמודי קטלוג נשמרים בקאש ומתעדכנים לפי TTL או webhook מביטריקס כשמוצר משתנה. Nuxt 3 תומך ב-useAsyncData() עם routeRules (stale-while-revalidate):
// nuxt.config.ts
routeRules: {
'/catalog/**': { swr: 3600 }, // кеш на час
'/product/**': { swr: 600 }, // кеш на 10 минут
'/cart': { ssr: false }, // корзина — только клиент
'/checkout': { ssr: false },
}לקטלוגים עם 50,000+ מוצרים, SSR עדיף על פני יצירת סטטי מלא — swr לנפח כזה ייקח שעות. תגי מטא הם משימה נפרדת. בביטריקס, תבניות SEO מוגדרות במאפייני בלוק מידע (תבניות כמו // nuxt.config.ts routeRules: { '/catalog/**': { swr: 3600 }, // кеш на час '/product/**': { swr: 600 }, // кеш на 10 минут '/cart': { ssr: false }, // корзина — только клиент '/checkout': { ssr: false }, } ). בגישת headless, יש לשרת תבניות אלה דרך API וליישם אותן ב-Nuxt באמצעות nuxt generate או {=this.Name} купить в Минске.
הרשאה: שתי גישות
OAuth 2.0 דרך המודול useHead(): הפרונטאנד מפנה ל-useSeoMeta(), המשתמש מתחבר בצד ביטריקס, מקבל rest, מחליף אותו ב-/oauth/authorize/. זרימה סטנדרטית, אבל חוויית המשתמש סובלת — הפניה לדומיין אחר.
נקודת קצה JWT מותאמת אישית: code מקבל שם משתמש/סיסמה, ביטריקס מאמתת דרך access_token, יוצרת סשן ומחזירה JWT. הפרונטאנד שומר את הטוקן ב-httpOnly cookie (לא ב-/api/auth/login — אחרת פגיעות XSS). refresh token מאריך את הסשן ללא הזנת סיסמה מחדש. פשוט יותר ליישום, חוויית משתמש טובה יותר.
מה הולך לאיבוד עם headless?
- עורך חזותי — לא עובד. התוכן מנוהל דרך פאנל הניהול של ביטריקס; הפרונטאנד מביא נתונים דרך API.
- קאש מרוכב — לא ישים. קאשינג בצד Nuxt (ISR) או CDN.
- קומפוננטות סטנדרטיות —
CUser::Login(),localStorageלא בשימוש. כל לוגיקת התצוגה על Vue. - החלפה עם 1C — עובדת ללא שינוי, מכיוון שהיא בצד השרת.
אילו שלבים כולל הפיתוח?
- ניתוח — אנו לומדים את ארכיטקטורת ביטריקס הנוכחית, דרישות UX וביצועים, קובעים את רשימת שיטות ה-API המותאמות אישית.
- עיצוב — אנו מפתחים מפרט API (OpenAPI), אב טיפוס ממשק, ומסכימים איתך.
- פיתוח — אנו כותבים שיטות REST מותאמות אישית, אפליקציית Vue, מגדירים SSR, משתלבים עם שירותים חיצוניים.
- בדיקות — בדיקות עומס (עם k6 או Artillery), אימות תגי SEO, תאימות דפדפנים.
- פריסה — הגדרת CI/CD, פריסה לייצור, ניטור.
מה כלול בעבודה?
- מפרט API מלא (OpenAPI) לכל השיטות המותאמות אישית.
- קוד מקור של אפליקציית Vue עם הערות.
- הוראות פריסה והגדרת CI/CD.
- בדיקות אוטומטיות לתרחישים קריטיים.
- הכשרת הצוות שלך לעבודה עם ארכיטקטורת headless.
- חודש של תמיכה טכנית לאחר ההשקה.
לוחות זמנים לפי היקף הפרויקט:
| היקף | מה כלול | לוח זמנים |
|---|---|---|
| קטלוג MVP | רשימה, כרטיס מוצר, פילטרים, SSR | 1–2 שבועות |
| חנות ללא חשבון | + סל, תשלום, סליקה | 3–4 שבועות |
| חנות מלאה | + חשבון, היסטוריית הזמנות, מועדפים, השוואה | 5–8 שבועות |
| פורטל B2B | + סוגי מחירים לפי קבוצה, קטלוגים אישיים, הזמנה מהירה | 8–12 שבועות |
Headless על ביטריקס הוא פשרה. פרונטאנד מודרני וגמישות בתמורה לאובדן חלק מהמערכת האקולוגית ועלויות תמיכה מוגדלות. הגישה מוצדקת לפרויקטים עם דרישות ממשק גבוהות, צוות פרונטאנד ייעודי, ותוכניות לריבוי-פלטפורמות. מעבר ל-headless יכול להפחית את עלויות תחזוקת הפרונטאנד בעד 30% הודות לעצמאות הצוות. כדי להעריך את הפרויקט שלך, צור איתנו קשר ונכין הצעה מסחרית עם לוחות זמנים ועלות מדויקים. בקש ייעוץ על פיתוח headless לחנות המקוונת שלך.

