מצב טיפוסי: מעצב יצר קטלוג עם פילטרים מונפשים, עדכוני סל מיידיים ומעברי עמודים ללא טעינה מחדש. מפתח הפרונטאנד מסתכל על התבניות 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 או לכתוב endpoint משל עצמך. סינון פאקטלי — ספירת מספר המוצרים עבור כל ערך פילטר, כמו ב-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 לאחסון מאפיינים נוספים וקאש מתויג. לדוגמה, בעדכון מחיר מוצר דרך agent, ניתן לפסול רק את הקאש המתויג מבלי להשפיע על עמודים אחרים. Agents ואירועים (`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 מוכן; לאחר hydration, האפליקציה עובדת כ-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/. זרימה סטנדרטית, אבל חווית המשתמש סובלת — הפניה לדומיין אחר.
endpoint 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), אב טיפוס UI, ומסכימים איתך.
- פיתוח — אנו כותבים שיטות 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 לחנות המקוונת שלך.

