לקוח מתלונן: כל לחיצה בחשבון האישי באתר 1C-Bitrix טוענת מחדש את העמוד, והמשתמש ממתין 2–3 שניות. אנו מפתחים SPA על React: לאחר הטעינה הראשונה, הנתונים נשלפים דרך REST API, ו-React Router מטפל במעברים ללא טעינות מלאות. כתוצאה מכך, עמודים נטענים תוך 200–400 אלפיות שנייה, עומס השרת יורד פי 4 בזכות מטמון בצד הלקוח. ובלי התקפי זעם של משתמשים.
הפורטפוליו שלנו כולל מעל 30 פרויקטי SPA עבור Bitrix: מחשבונות אישיים ועד פורטלי B2B עם קטלוגים של 100,000 פריטים. יש לנו ניסיון של שנים בפיתוח Bitrix, מה שעוזר להימנע מטעויות אינטגרציה אופייניות. צרו קשר לבדיקת הפרויקט שלכם.
איזו בעיה פותר SPA של React?
הכאב העיקרי של אתרי Bitrix קלאסיים הוא טעינה מלאה של העמוד בכל פעולה. המשתמש לוחץ, הדפדפן שולח בקשה, השרת מייצר HTML, הלקוח מקבל ומציג אותו. כל ניווט אורך 1–3 שניות. בחשבון אישי, שבו סשן טיפוסי כולל 20–30 לחיצות, זמן ההמתנה הכולל מגיע לדקה. SPA מבטל זאת: לאחר טעינת עמוד המעטפת, כל המעברים הבאים מטופלים בצד הלקוח. נתונים נשלפים דרך REST API, והממשק מתעדכן מיידית.
ארכיטקטורה של SPA של React עבור Bitrix
נקודת כניסה ו-__INITIAL_STATE__
ה-SPA מורכב דרך נקודת כניסה יחידה בתבנית Bitrix. אנו מזריקים נתונים ראשוניים דרך window.__INITIAL_STATE__ — זה מפחית את מספר הבקשות בעת ההפעלה. כפי שצוין ב-React Router, גישה זו מבטיחה ניווט חלק ללא אובדן מצב.
דוגמה להזרקת מצב ראשוני
// /local/templates/main/components/bitrix/system.auth.form/lk/template.php
// Или отдельная страница /lk/index.php
defined('B_PROLOG_INCLUDED') && (B_PROLOG_INCLUDED === true) || die();
?>
<!DOCTYPE html>
<html>
<head>
<title>Личный кабинет</title>
<?php $APPLICATION->ShowHead(); ?>
</head>
<body>
<!-- Данные для инициализации SPA -->
<script>
window.__INITIAL_STATE__ = <?= json_encode([
'user' => $arResult['USER'],
'csrfToken'=> bitrix_sessid(),
'apiBase' => '/local/ajax/',
]) ?>;
</script>
<div id="spa-root"></div>
<?php $APPLICATION->ShowFooter(); ?>
<script type="module" src="/local/js/dist/lk.js"></script>
</body>
</html> React Router: ניווט ללא טעינה מחדש
// /local/js/src/lk/App.tsx
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
export function App() {
const { data: auth } = useAuth();
if (!auth?.isAuthorized) {
// Редирект на стандартную авторизацию Битрикс
window.location.href = '/auth/?backurl=' + encodeURIComponent(window.location.pathname);
return null;
}
return (
<BrowserRouter basename="/lk">
<AppLayout>
<Routes>
<Route index element={<Dashboard />} />
<Route path="orders" element={<Orders />} />
<Route path="orders/:id" element={<OrderDetail />} />
<Route path="profile" element={<Profile />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</AppLayout>
</BrowserRouter>
);
}חשוב: השתמשו ב-// /local/templates/main/components/bitrix/system.auth.form/lk/template.php // Или отдельная страница /lk/index.php defined('B_PROLOG_INCLUDED') && (B_PROLOG_INCLUDED === true) || die(); ?> <!DOCTYPE html> <html> <head> <title>Личный кабинет</title> <?php $APPLICATION->ShowHead(); ?> </head> <body> <!-- Данные для инициализации SPA --> <script> window.__INITIAL_STATE__ = <?= json_encode([ 'user' => $arResult['USER'], 'csrfToken'=> bitrix_sessid(), 'apiBase' => '/local/ajax/', ]) ?>; </script> <div id="spa-root"></div> <?php $APPLICATION->ShowFooter(); ?> <script type="module" src="/local/js/dist/lk.js"></script> </body> </html> בתוך BrowserRouter כדי ש-React Router ידע את נתיב הבסיס ולא ישבור את הניווט.
ניהול מצב: Zustand
עבור SPA ברמת מורכבות בינונית, Zustand הוא הבחירה האופטימלית על פני Redux. הוא דורש פחות קוד וקל יותר לתחזוקה.
// /local/js/src/lk/store/cartStore.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { bitrixApi } from '../api/bitrix';
interface CartState {
items: CartItem[];
total: number;
addItem: (productId: number, quantity: number) => Promise<void>;
removeItem: (itemId: number) => Promise<void>;
syncWithServer: () => Promise<void>;
}
export const useCartStore = create<CartState>()(
persist(
(set, get) => ({
items: [],
total: 0,
addItem: async (productId, quantity) => {
const result = await bitrixApi.post<{ items: CartItem[]; total: number }>(
'cart.add',
{ product_id: productId, quantity }
);
set({ items: result.items, total: result.total });
},
removeItem: async (itemId) => {
const result = await bitrixApi.post<{ items: CartItem[]; total: number }>(
'cart.remove',
{ item_id: itemId }
);
set({ items: result.items, total: result.total });
},
syncWithServer: async () => {
const result = await bitrixApi.get<{ items: CartItem[]; total: number }>('cart.get');
set({ items: result.items, total: result.total });
},
}),
{
name: 'bitrix-cart',
}
)
);
טיפול בשגיאות ומצב לא מקוון
ה-SPA חייב לטפל בשגיאות רשת בצורה אלגנטית. אנו מיישמים Error Boundary שתופס שגיאות רינדור ומציג למשתמש ממשק שחזור. לחוסן במצב לא מקוון, Service Worker שומר במטמון בקשות GET ל-API.
// Глобальный Error Boundary
class ApiErrorBoundary extends Component<Props, State> {
state = { hasError: false, error: null };
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
render() {
if (this.state.hasError) {
return <ErrorScreen error={this.state.error} onRetry={() => this.setState({ hasError: false })} />;
}
return this.props.children;
}
} למה SSR לא תמיד נחוץ?
עבור אזורים סגורים (חשבון אישי, פאנל ניהול), רינדור בצד השרת אינו נדרש — בוטים לא מבצעים אינדוקס שלהם. עבור עמודים ציבוריים (קטלוג, מאמרים), אנו משתמשים באחת מהגישות הבאות:
- Next.js עם בקשות API ל-Bitrix בצד השרת — הגישה הנקייה ביותר.
- Vite SSR — קשה יותר להגדרה, אך אינו דורש שינוי של הפריימוורק.
- יצירת אתר סטטי (SSG) — לתוכן שמשתנה לעיתים רחוקות.
הבחירה תלויה בשיעור התוכן הציבורי. אם 80% מהפונקציונליות היא חשבון אישי, SSR הוא מיותר.
איך SPA עדיף על הגישה הקלאסית?
נשווה מדדים מרכזיים באמצעות דוגמה של פורטל B2B עם קטלוג של 50,000 פריטים:
| קריטריון | SPA (React) | MPA (סטנדרטי) |
|---|---|---|
| זמן טעינה לאחר לחיצה ראשונה | 200–500 אלפיות שנייה | 1–3 שניות |
| מספר בקשות לשרת | 1 (נתונים) | 1 (עמוד מלא) |
| עומס שרת | נמוך (מטמון) | גבוה (ייצור) |
| חלקות הממשק | גבוהה | בינונית |
טבלה נוספת — השוואת גישות רינדור:
| גישה | מהירות | SEO | מורכבות |
|---|---|---|---|
| CSR (לקוח) | מהיר לאחר טעינה | לא | נמוכה |
| SSR (שרת) | מסך ראשון מהיר | כן | גבוהה |
| SSG (סטטי) | מיידי | כן | בינונית |
SPA עם CSR מפחית את זמן האינטראקציה ב-60% ומפחית את מספר הבקשות פי 4 — הוכח בפרויקטים. החיסכון בתשתית השרת מגיע ל-40–60% מהעלויות הנוכחיות.
תהליך הפיתוח
- ניתוח API — קביעה אילו נתונים Bitrix מספק, עיצוב נקודות קצה.
- עיצוב ארכיטקטורה — בחירת הסט (React, Zustand, React Router, בניית Vite).
- פיתוח רכיבים — יצירת ערכת UI, עמודים, ניהול מצב.
- אינטגרציה עם Bitrix — חיבור REST API, הגדרת CORS, הזרקת מצב ראשוני.
- בדיקות — בדיקות עומס (1000 משתמשים במקביל), תרחישי שגיאה.
- פריסה — הגדרת CI/CD, מטמון, HTTPS.
לוח זמנים ומה כלול
לוח זמנים: בין 2 ל-6 שבועות. העלות מחושבת באופן אישי לאחר בדיקת הפרויקט שלכם. אנו לא משתמשים בפתרונות תבניתיים — כל SPA נכתב לצרכים עסקיים ספציפיים.
העבודה כוללת:
- קוד מקור ב-Git עם היסטוריית commits
- תיעוד API וארכיטקטורה
- הוראות פריסה
- הדרכת צוות (שעתיים מקוונות)
- אחריות ל-6 חודשים על באגים שזוהו
- תמיכה לאחר השקה (אופציונלי)
טעויות אופייניות בפיתוח SPA על Bitrix
- שכפול לוגיקה עסקית ב-PHP וב-JS — שמרו על גבול ברור: Bitrix רק API, React רק UI.
- התעלמות ממטמון — יש להגדיר מטמון מתויג של רכיבי Bitrix.
- חוסר ב-Error Boundary — שגיאות לא מטופלות קורסות את כל ה-SPA.
הניסיון של הצוות שלנו עוזר להימנע מבעיות אלה. צרו קשר להערכת הפרויקט שלכם — ננתח את האתר הנוכחי שלכם ונציע ארכיטקטורה אופטימלית. או הזמינו פיתוח SPA — נעריך את המשימה תוך יום אחד.

