Клиент жалуется: каждый клик в личном кабинете на сайте 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 — мы оценим задачу за один день.







