Клієнт скаржиться: кожен клік в особистому кабінеті на сайті 1С-Бітрікс — перезавантаження сторінки, користувач чекає 2–3 секунди. Ми займаємося розробкою SPA на React: після першого завантаження дані підтягуються через REST API, а React Router керує переходами без повного перезавантаження. У результаті сторінки завантажуються за 200–400 мс, навантаження на сервер падає в 4 рази завдяки кешуванню на клієнті. І жодних істерик у користувачів.
Наше портфоліо включає понад 30 SPA-проєктів для Бітрікса: від особистих кабінетів до B2B-порталів із каталогами на 100 000 товарів. Ми маємо багаторічну експертизу в галузі Бітрікс-розробки, що дозволяє уникнути типових помилок інтеграції. Зв'яжіться з нами для безкоштовного аудиту вашого проєкту.
Яку проблему вирішує SPA на React?
Головна біда класичних Бітрікс-сайтів — повне перезавантаження сторінки при кожній дії. Користувач клікає, браузер надсилає запит, сервер генерує HTML, клієнт отримує і рендерить. На кожну навігацію йде 1–3 секунди. В особистому кабінеті, де типова сесія включає 20–30 кліків, сумарне очікування сягає хвилини. SPA усуває це: після завантаження shell-сторінки всі подальші переходи обробляються на клієнті. Дані запитуються через REST API, інтерфейс оновлюється миттєво.
Архітектура SPA на React для Бітрікса
Точка входу та __INITIAL_STATE__
SPA монтується через єдину точку входу в Бітрікс-шаблоні. Ми впроваджуємо початкові дані через 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> ); } Важливо: використовуйте basename у 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' } ) ); Обробка помилок і offline-режим
SPA повинен коректно обробляти помилки мережі. Реалізуємо Error Boundary, який ловить помилки рендеру і показує користувачеві інтерфейс відновлення. Для offline-стійкості 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-запитами до Бітрікса на стороні сервера — найчистіший підхід.
- 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 — визначаємо, які дані віддає Бітрікс, проєктуємо ендпоінти.
- Проєктування архітектури — обираємо стек (React, Zustand, React Router, збірка Vite).
- Розробка компонентів — створюємо UI-кіт, сторінки, state management.
- Інтеграція з Бітріксом — підключаємо REST API, налаштовуємо CORS, впроваджуємо initial state.
- Тестування — навантажувальне (1000 одночасних користувачів), сценарії помилок.
- Деплой — налаштовуємо CI/CD, кешування, HTTPS.
Строки та що входить
Строки від 2 до 6 тижнів. Вартість проєкту розраховується індивідуально після аудиту вашого проєкту. Ми не використовуємо типові рішення — кожен SPA пишеться під конкретні бізнес-завдання.
У роботу входить:
- Вихідний код у Git з історією комітів
- Документація по API та архітектурі
- Інструкція з розгортання
- Навчання команди (2 години онлайн)
- Гарантія 6 місяців на виявлені баги
- Підтримка після запуску (опціонально)
Типові помилки при розробці SPA на Бітрікс
- Дублювання бізнес-логіки в PHP і JS — тримайте межу чітко: Бітрікс тільки API, React тільки UI.
- Ігнорування кешування — теговане кешування компонентів Бітрікса має бути налаштоване.
- Відсутність Error Boundary — необроблені помилки руйнують усе SPA.
Уникнути цих проблем допомагає досвід нашої команди. Зв'яжіться з нами для безкоштовної оцінки вашого проєкту — ми проаналізуємо поточний сайт і запропонуємо оптимальну архітектуру. Або замовте розробку SPA — ми оцінимо завдання за один день.







