Разработка личного кабинета на 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 месяца.







