Розробка особистого кабінету на React для 1С-Бітрікс
Штатний особистий кабінет у 1С-Бітрікс — це набір PHP-компонентів bitrix:sale.personal.*, які рендеряться на сервері, віддають повну HTML-сторінку і при будь-якій дії користувача (зміна адреси доставки, перегляд статусу замовлення) виконують повний page reload. На невеликих магазинах це терпимо. Коли в кабінеті з'являється історія замовлень на 200+ позицій, система лояльності, кілька адрес доставки, документи та інтеграція із зовнішніми сервісами — штатний підхід стає вузьким місцем за UX і продуктивністю.
React-кабінет вирішує завдання інакше: сервер віддає тільки дані через REST, інтерфейс живе в браузері. Це означає миттєві переходи між розділами, оновлення даних без перезавантаження, можливість будувати складні інтерактивні форми без перекомпонування сторінки.
Архітектура інтеграції
Є два принципово різних способи вбудувати React-кабінет у Бітрікс.
Варіант 1: React всередині шаблону Бітрікс. На PHP-сторінці /personal/ монтується React-застосунок у контейнер <div id="personal-root"></div>. Бітрікс відповідає за авторизацію, SEO (title, meta), загальний layout (шапка, футер). React керує тільки вмістом кабінету. Роутинг — через React Router з BrowserRouter, історія браузера синхронізується з URL.
Цей варіант простіший в інтеграції: авторизація через стандартний $USER->Login(), сесія Бітрікс передається автоматично, CSRF-токен береться з BX.bitrix_sessid().
Варіант 2: SPA з JWT-авторизацією. React-застосунок живе окремо (окремий домен або піддомен), взаємодіє з Бітрікс виключно через REST API з JWT-токенами. Авторизація — через кастомний endpoint, токен зберігається в httpOnly cookie або localStorage. Цей варіант виправданий, коли кабінет має працювати і з мобільним застосунком, і з веб-версією через одне API.
Для більшості проєктів оптимальний Варіант 1 — він простіший у підтримці, не потребує окремого деплою, авторизація вже вирішена.
API-шар на стороні Бітрікс
React-компоненти працюють з даними через AJAX-запити до Бітрікс. Для цього створюється контролер у /local/php_interface/include/api/personal/:
// Приклад: endpoint для списку замовлень
class PersonalOrdersController extends \Bitrix\Main\Engine\Controller
{
public function getListAction(int $page = 1, int $limit = 20): array
{
$userId = \Bitrix\Main\Engine\CurrentUser::get()->getId();
$orderList = \Bitrix\Sale\Order::getList([
'filter' => ['USER_ID' => $userId],
'select' => ['ID', 'DATE_INSERT', 'PRICE', 'STATUS_ID', 'CURRENCY'],
'order' => ['DATE_INSERT' => 'DESC'],
'limit' => $limit,
'offset' => ($page - 1) * $limit,
]);
$orders = [];
while ($order = $orderList->fetch()) {
$orders[] = $order;
}
return [
'orders' => $orders,
'total' => \Bitrix\Sale\Internals\OrderTable::getCount(['USER_ID' => $userId]),
];
}
}
Роутинг у Бітрікс через local/ajax/personal.php з диспетчером або через \Bitrix\Main\Engine\Router. Для CSRF-захисту всі POST-запити з React передають заголовок BX-Ajax: true і токен сесії.
Структура React-застосунку
src/
personal/
api/ # axios-інстанс, типи запитів
components/ # перевикористовувані UI-елементи
pages/
Orders/ # історія замовлень
OrderDetail/ # детальна сторінка замовлення
Profile/ # дані профілю
Addresses/ # адреси доставки
Loyalty/ # бонусна програма
store/ # стан (Zustand або Redux Toolkit)
App.tsx
router.tsx
Управління станом: для простих кабінетів достатньо React Query (кеш запитів + синхронізація) без глобального стору. Для складних — Zustand як легша альтернатива Redux.
Кейс: кабінет для B2B-дистриб'ютора
Оптовий постачальник електроніки, ~1 500 активних клієнтських акаунтів. Завдання: особистий кабінет для менеджерів клієнта — можливість бачити історію закупівель, формувати повторне замовлення з історії, управляти кількома юридичними особами в одному акаунті, завантажувати закривальні документи.
Штатний Бітрікс-кабінет не підтримував мультиюрособу в принципі, а історія замовлень на 3 000+ рядків рендерилась сервером 4–6 секунд.
Що реалізували:
-
API-контролер для замовлень із серверною пагінацією, фільтрацією за датою/статусом і пошуком за номером замовлення. Запит на сторінку з 50 позицій — 80–120 мс проти 4+ секунд при повному рендері.
-
Мультиюрособа через кастомну таблицю
local_personal_company(зв'язокuser_id → company_id), перемикач компаній у шапці кабінету з перезавантаженням контексту через React QueryinvalidateQueries. -
«Повторити замовлення» — кнопка в історії, яка додає всі позиції замовлення до кошика через
\Bitrix\Sale\Basket::create()і робить bulk-insert товарів. На фронті — анімований індикатор, тостове сповіщення про успіх. -
Документи — інтеграція з 1С: замовлення документів через REST 1С, статус генерації через polling кожні 3 секунди, завантаження PDF напряму з 1С за тимчасовим посиланням.
| Метрика | До | Після |
|---|---|---|
| Завантаження сторінки замовлень | 4.2 сек | 0.9 сек |
| Повторне замовлення | 5 кроків, 2 хвилини | 1 клік, 3 секунди |
| Звернення в підтримку щодо документів | ~40/міс | ~8/міс |
Авторизація та безпека
Всі API-запити з React виконуються тільки для авторизованого користувача. Перевірка на сервері:
if (!\Bitrix\Main\Engine\CurrentUser::get()->isAuthorized()) {
throw new \Bitrix\Main\AccessDeniedException('Not authorized');
}
Дані одного користувача недоступні іншому: всі запити фільтруються за USER_ID із сесії, ID з URL або параметрів запиту ігнорується або звіряється з сесійним.
XSS-захист: React екранує виведення за замовчуванням, HTML з Бітрікс не вставляється через dangerouslySetInnerHTML без санітизації.
Збірка та деплой
Vite із налаштованим проксі для API в development-режимі. Production-збірка деплоїться в /local/assets/personal/, підключається в шаблоні компонента:
// template.php
\Bitrix\Main\Page\Asset::getInstance()->addJs(
'/local/assets/personal/index.js'
);
Для cache busting — версіонування через content hash у Vite (rollupOptions.output.assetFileNames).
Склад робіт
- Проєктування API: ендпоінти, структура даних, пагінація
- Розробка серверної частини: контролери, авторизація, права доступу
- Розробка React-застосунку: роутинг, компоненти, стан
- Інтеграція з модулями Бітрікс:
sale,catalog,crmза потреби - Збірка, деплой, налаштування кешування API-відповідей
Терміни залежать від набору функцій: мінімальний кабінет (профіль + замовлення + адреси) — 3–4 тижні, повнофункціональний B2B-кабінет з інтеграціями — 2–4 місяці.







