Разработка SPA на React для 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка SPA на React для 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1173
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    745
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Разработка SPA на React для 1С-Битрикс

Single Page Application поверх 1С-Битрикс — это когда браузер загружает одну HTML-страницу, а дальнейшая навигация происходит без полной перезагрузки. Битрикс отдаёт данные через API, React Router управляет URL и переходами. Подходит для личных кабинетов, B2B-порталов, административных интерфейсов — везде, где пользователь долго работает в системе и перезагрузка страницы разрушает UX.

Структура SPA и точка входа

SPA монтируется через единственную точку входа в Битрикс-шаблоне:

// /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: маршрутизация SPA

// /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' }
    )
);

Серверный рендеринг (SSR) — нужен ли?

SPA на клиентском рендеринге имеет проблему: поисковые боты плохо индексируют контент, который генерируется JS. Для личного кабинета (закрытый раздел) это не важно. Для публичного каталога — критично.

Если SPA включает публичные страницы, нужен SSR. Варианты:

  • Next.js с API-запросами к Битриксу на стороне сервера — наиболее чистый подход
  • Vite SSR — сложнее в настройке, но не требует смены фреймворка
  • Пре-рендеринг статических страниц (SSG) для страниц с редко меняющимся контентом

Для закрытых разделов (личный кабинет, B2B-портал) SSR не нужен — экономьте на сложности.

Обработка ошибок и offline-режим

SPA должен корректно обрабатывать ошибки сети и 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;
    }
}

Для offline-устойчивости Service Worker кэширует GET-запросы к API. При потере соединения пользователь видит кэшированные данные с пометкой «офлайн-режим», а POST-запросы ставятся в очередь и выполняются при восстановлении сети.

SPA в Битрикс-проекте требует дисциплины на стыке двух систем: Битрикс должен давать данные через API, React — только отображать и обрабатывать ввод. Как только бизнес-логика начинает дублироваться — часть в PHP-компонентах, часть в JS — проект становится нечитаемым. Держите границу чёткой.