Обзор технологий для разработки сайтов на Битрикс
Rus
Eng
Обзор технологий для разработки сайтов на Битрикс
Решаю сложные технические задачи для Bitrix и 1С: от аудита чужого кода до разработки сайтов и настройки сложных интеграций с гарантией результата
Рекомендую

Хостинг для сайта

Если выбираете хостинг под проект — советую Timeweb. Современная инфраструктура, широкий выбор тарифов от стартовых до VPS под нагрузку, отзывчивая техподдержка, которая отвечает по существу, а не отписками. Я сам держу на нём часть своих проектов и рекомендую клиентам.

Перейти Партнёрская ссылка. Для вас цена не меняется.

Современная разработка на Битрикс: обзор технологий, инфраструктуры и практик

Актуально на 2026 год. Материал проверялся для 1С-Битрикс: Управление сайтом (актуальные релизы), PHP 8.2/8.3, MySQL 8.0 / Percona Server 8.0. Перед применением сверяйтесь с официальной документацией вендора: поддержка версий PHP и модулей зависит от релиза ядра.

Почему это обзор, а не инженерный гид

Изначально этот материал задумывался как инженерно-методический разбор современной разработки на Битрикс: с полными примерами, разбором ошибок и пошаговыми инструкциями. Но чем дальше я заходил, тем очевиднее становилось, что тема не помещается в одну статью. Когда количество подтем перевалило за двадцать, объём черновика перевалил за пятнадцать тысяч строк, а каждая тема при этом была в лучшем случае не раскрыта — стало понятно, что такой формат не работает. Раскрывать каждую тему по-настоящему — это отдельные статьи, а не одна.

Поэтому концепция поменялась. Перед вами — обзор технологий для разработки сайтов на Битрикс. Что применять, когда это нужно и как использовать. По каждой теме — сжато, по делу, с примерами и с разбором плюсов и минусов, чтобы было понятно, стоит ли вообще браться за эту технологию в конкретном проекте. Углублять или нет — решайте сами.

Материал ориентирован на команды, которые занимаются созданием сайтов на 1С-Битрикс — от небольших студий до enterprise-разработки. Всё, что здесь описано, применяется при развёртывании Битрикс-проектов в промышленном режиме и при развитии уже существующих интернет-магазинов на Битрикс.

Важно: примеры кода в статье — учебные и упрощённые. Они показывают подход, а не готовое продакшен-решение. Перед использованием на боевом сервере адаптируйте их под проект и протестируйте на staging.

Часть 1. Инфраструктура и DevOps

Почему BitrixVM — чаще всего только для старта

BitrixVM — это готовый образ виртуальной машины с преднастроенным стеком: Nginx, PHP, MySQL, memcached, push&pull. Для быстрого развёртывания тестового сайта, обучения или пилотного проекта она удобна: поставил образ, запустил скрипт настройки, получил работающий Битрикс за полчаса.

Плюсы: быстрый старт, всё уже настроено, меньше шансов ошибиться на этапе развёртывания.

Минусы: тянет за собой пул пакетов, версии которых отстают от актуальных; обновления платформы могут сломать конфигурацию Nginx или PHP; нельзя гибко управлять версиями PHP для разных проектов на одном сервере.

Для продакшена обычно предпочтительнее чистый стек на Ubuntu или Debian с Nginx, PHP-FPM 8.2 или 8.3, Percona Server или MySQL 8.0. Версия PHP выбирается под конкретный проект: Bitrix стабильно работает на 8.2; 8.3 подходит для новых сайтов без legacy-модулей, но совместимость нужно проверять по матрице вендора.

Nginx-конфиг для Битрикс: ЧПУ, композит, статика, таймауты

Конфигурация Nginx для разработки на Битрикс имеет несколько обязательных мест. Первое — try_files с urlrewrite.php, иначе ЧПУ работать не будет. Второе — отдача композитного кэша напрямую из Nginx: если файл готового html существует, отдать его; иначе передать запрос в PHP-FPM. Третье — корректная обработка статики. Четвёртое — увеличенные таймауты fastcgi_read_timeout для тяжёлых операций. Пятое — директива client_max_body_size, которая по умолчанию в Nginx равна 1 МБ и режет загрузку файлов через админку и формы. Для интернет-магазина с загрузкой изображений и документов её нужно поднять минимум до 64 МБ, лучше — до 128 МБ, синхронизировав с upload_max_filesize и post_max_size в PHP.

Композитный кэш Bitrix хранится в виде готовых index.html по пути /bitrix/html_pages/<host><uri>/index.html. Именно этот путь и нужно проверять первым:

server {
    listen 80;
    server_name domain.ru;
    root /var/www/domain.ru;

    index index.php;

    client_max_body_size 128M;
    client_body_buffer_size 4M;

    location / {
        try_files /bitrix/html_pages/$host$uri/index.html $uri $uri/ /bitrix/urlrewrite.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_read_timeout 300;
        fastcgi_send_timeout 300;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
        expires 30d;
        access_log off;
    }

    # Защита от прямого доступа к композитному кэшу
    location ~ ^/bitrix/html_pages/ {
        internal;
    }
}

Без location ~ ^/bitrix/html_pages/ { internal; } композитные index.html открываются по прямой ссылке — это утечка контента и потенциальная проблема с индексацией. Без правильного пути $host$uri/index.html композит не отдаётся вообще, и весь смысл его включения теряется: нагрузка на PHP-FPM остаётся прежней.

Плюсы композитного кэша: снимает нагрузку с PHP-FPM в разы, страницы отдаются за миллисекунды. Минусы: не работает на динамических страницах с формами, корзиной, персональными данными — там композит приходится отключать. Для интернет-магазина на Битрикс с посещаемостью от 50 000 хостов в сутки композит — важный элемент, но применять его нужно точечно.

Docker и Docker Compose

Разворачивать Битрикс-проект вручную на каждом сервере — трудозатратно и чревато расхождениями между окружениями. Docker и Docker Compose дают воспроизводимость: одинаковый стек на локальной машине, на staging и на production. Для Bitrix есть готовые образы, но лучше собирать свой на базе php:8.2-fpm с нужными расширениями.

version: '3.8'

services:
  app:
    build: ./docker/php
    volumes:
      - ./:/var/www/html
    depends_on:
      - db
      - redis

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./:/var/www/html
      - ./docker/nginx/bitrix.conf:/etc/nginx/conf.d/default.conf

  db:
    image: percona:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
    volumes:
      - db_data:/var/lib/mysql

  redis:
    image: redis:7-alpine

volumes:
  db_data:

Плюсы: одинаковое окружение у всей команды, быстрый онбординг новых разработчиков, легко поднять десяток окружений для параллельной работы. Минусы: на продакшене Docker даёт накладные расходы по производительности (обычно незначительные, но зависят от конфигурации сети, файловой системы и нагрузки), требует дисциплины в работе с томами и секретами, добавляет слой абстракции, который нужно понимать всей команде. Для небольших проектов на одном сервере классическое развёртывание без контейнеров может быть проще.

Multi-environment: dev / stage / prod

Три окружения — минимум для коммерческой разработки на Битрикс. Локальная разработка ведётся на dev, тестирование перед выкаткой — на stage, боевой сервер — prod. Каждое окружение имеет свои настройки: пути к базе, ключи API, уровень логирования. Всё это удобно выносить в .env и подхватывать через сторонние библиотеки вроде symfony/dotenv. Замечу: .env — это не встроенный механизм Битрикс, а внешняя практика, которую нужно явно подключать в проекте.

Правило простое: .env никогда не попадает в репозиторий. В репозитории лежит .env.example с перечнем переменных, реальные значения настраиваются на каждом сервере отдельно.

Git-архитектура и .gitignore

Самая распространённая ошибка при создании сайтов на Битрикс — тащить в Git папку /bitrix целиком. Ядро платформы — это не ваш код, оно обновляется вендором, и его версионирование создаёт конфликты при каждом обновлении. Современный подход: весь кастомный код держится в /local, а ядро и пользовательские файлы не версионируются.

В репозиторий попадает только то, что относится к проекту: /local, конфиги, composer.json и composer.lock. Каталог /upload содержит пользовательские файлы (изображения, документы, загруженные через админку) и не должен версионироваться — в Git можно хранить только /upload/.htaccess или пустую структуру каталога, если это требуется для деплоя.

/bitrix/*
!/bitrix/.htaccess

/upload/*
!/upload/.htaccess

/local/cache/
/local/logs/

/vendor/
*.log
*.sql
*.bak
*.zip
.env
.env.*
!.env.example
.idea/

Если в проекте исторически есть кастомные шаблоны или компоненты внутри /bitrix, это исключение нужно явно оговорить и по возможности перенести в /local. Хранить /bitrix/templates и /bitrix/components в Git — устаревшая практика, которая приводит к конфликтам при обновлении ядра.

Плюсы: чистая история, нет конфликтов с ядром, быстрый clone. Минусы: нужно один раз аккуратно настроить, иначе рискуете случайно закоммитить ядро или, наоборот, потерять local/php_interface при обновлении.

Branching strategy (упрощённый GitFlow)

Для Битрикс-разработки хорошо работает упрощённый GitFlow. Две долгоживущие ветки: master — стабильная, с неё разворачивается production, и develop — ветка разработки, с неё идёт деплой на staging. Каждая задача ведётся в отдельной ветке feature/*, которая вливается в develop через merge request. Срочные правки — hotfix/*, они вливаются и в master, и в develop.

Плюсы: предсказуемость, никто не пушит в стабильную ветку напрямую, легко откатить неудачный релиз. Минусы: для проекта с одним разработчиком GitFlow — избыточная церемония, проще trunk-based development с короткоживущими ветками и частыми релизами.

Composer: управление зависимостями

Composer в Bitrix — это не про установку ядра, а про сторонние библиотеки. Логирование через Monolog, работа с REST API через Guzzle, внедрение зависимостей через php-di.

{
    "require": {
        "monolog/monolog": "^3.0",
        "guzzlehttp/guzzle": "^7.0",
        "php-di/php-di": "^7.0"
    },
    "autoload": {
        "psr-4": {
            "ProjectScope\\": "local/lib/"
        },
        "classmap": [
            "local/components/project/*/src"
        ]
    },
    "config": {
        "optimize-autoloader": true,
        "sort-packages": true
    }
}

Плюсы: стандарт индустрии, autoload вместо ручных require, простая установка обновлений. Минусы: на некоторых shared-хостингах composer недоступен, старые версии PHP не поддерживаются современными библиотеками. Для проектов на актуальном PHP 8.2+ проблем нет.

CI/CD: пайплайн build → test → deploy

При деплое через rsync критично исключить /bitrix и /upload — иначе опция --delete снесёт на сервере ядро платформы и пользовательские файлы, и проект перестанет работать в течение секунды. Помимо этого исключаются каталоги кэша, логи и локальные настройки:

stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - composer install --no-dev --optimize-autoloader
    - npm ci && npm run build

test:
  stage: test
  script:
    - vendor/bin/phpstan analyse
    - vendor/bin/php-cs-fixer fix --dry-run --diff
    - vendor/bin/phpunit

deploy:
  stage: deploy
  script:
    - rsync -a --delete
        --exclude=/bitrix
        --exclude=/upload
        --exclude=/local/cache
        --exclude=/local/logs
        --exclude=/bitrix/html_pages
        --exclude=/.env
        ./ user@server:/var/www/domain.ru/
    - ssh user@server "cd /var/www/domain.ru && composer install --no-dev"

Плюсы: автоматизация, воспроизводимость деплоя, откат через git revert. Минусы: первичная настройка требует времени, для небольших проектов с одним разработчиком сложность не всегда окупается. Но если релизы хотя бы раз в неделю — CI/CD оправдан. Исключения в rsync — не деталь, а обязательная часть пайплайна.

Backup strategy

Бэкап при разработке на Битрикс — это не «сделаем потом». Обязательны две вещи: дамп базы и копия файлов. Дамп делается через mysqldump с опцией --single-transaction, чтобы не блокировать таблицы.

mysqldump --single-transaction --routines --triggers \
  --user=${DB_USER} --password=${DB_PASSWORD} \
  ${DB_NAME} | gzip > /backups/db_$(date +%Y%m%d_%H%M%S).sql.gz

Плюсы: минимальная страховка от катастрофы. Минусы: mysqldump на миллионном каталоге может занимать часы и потреблять много I/O. Для больших проектов лучше использовать Percona XtraBackup — он делает горячие бэкапы без блокировки таблиц.

Часть 2. База данных

Когда инфоблок избыточен

Инфоблоки — мощный инструмент, но каждое свойство — запись в отдельной таблице, каждый фильтр — JOIN. Для блога, новостей, каталога товаров инфоблок оправдан. Для справочника городов или списка статусов — нет. Признак: данные плоские, иерархии нет, полей немного, фильтрация простая.

Highload-блок или кастомная ORM-таблица (DataManager)

Highload-блок — генератор таблиц на основе D7 ORM, создаётся из админки, поддерживает UF-свойства, даёт готовый интерфейс. Собственная ORM-таблица — класс-наследник Bitrix\Main\Entity\DataManager, полный контроль над схемой, но интерфейс и работу с данными пишете сами.

Плюсы Highload-блока: быстро создать, готовый UI, не нужно писать код админки. Минусы: только простые индексы, нет внешних ключей, нет миграций. Плюсы DataManager: полный контроль над индексами и связями, миграции, типизация. Минусы: всё нужно писать самому, включая интерфейс.

Критерий: нужны составные индексы и связи — DataManager; данные плоские и нужен готовый интерфейс — Highload-блок. Для каталога с миллионом товаров Highload-блок часто не подходит именно из-за невозможности добавить составной индекс.

Миграции: MigrationRunner, up()/down(), таблица версий

Bitrix не имеет встроенного механизма миграций, поэтому нужен собственный раннер. Он состоит из трёх частей: таблица версий в базе, классы миграций с методами up() и down(), и раннер, который применяет только новые миграции.

Важно: пример ниже — учебный. В продакшене нужны транзакции на миграцию, блокировка от параллельного запуска, контрольные суммы, лимит попыток отката и логирование. Не копируйте код в боевой проект без адаптации.

Таблица версий создаётся один раз при инициализации:

CREATE TABLE project_migrations (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    VERSION VARCHAR(255) NOT NULL UNIQUE,
    APPLIED_AT DATETIME NOT NULL
);

Класс миграции — обычный PHP-класс с двумя методами. Никаких наследований от ядра, чтобы миграция не зависела от версии Bitrix:

&lt;?php

class Migration20260101AddPhoneColumn
{
    public function up(): void
    {
        $connection = \Bitrix\Main\Application::getConnection();
        $connection->queryExecute("
            ALTER TABLE project_orders
            ADD COLUMN PHONE VARCHAR(20) DEFAULT NULL
        ");
    }

    public function down(): void
    {
        $connection = \Bitrix\Main\Application::getConnection();
        $connection->queryExecute("
            ALTER TABLE project_orders
            DROP COLUMN PHONE
        ");
    }
}

Раннер сканирует каталог с миграциями, сравнивает имена классов с записями в таблице версий и применяет только те, которых там нет. Откат вызывается вручную — down() нужен, когда миграция сломала прод и надо вернуться к прежней схеме:

&lt;?php

class MigrationRunner
{
    /** @var string Каталог с классами миграций */
    private string $migrationsDir;

    public function __construct(string $migrationsDir)
    {
        $this->migrationsDir = rtrim($migrationsDir, '/');
    }

    /**
     * Применяет все новые миграции из каталога.
     *
     * @return array Список применённых версий
     */
    public function run(): array
    {
        $applied = $this->getAppliedVersions();
        $migrations = $this->discoverMigrations();
        $appliedNow = [];

        foreach ($migrations as $version => $class) {
            if (in_array($version, $applied, true)) {
                continue;
            }

            /** @var object $instance */
            $instance = new $class();

            if (!method_exists($instance, 'up')) {
                throw new \RuntimeException("Migration {$class} has no up() method");
            }

            $instance->up();
            $this->markApplied($version);
            $appliedNow[] = $version;
        }

        return $appliedNow;
    }

    /**
     * Откатывает указанную версию.
     *
     * @param string $version Версия миграции
     * @return void
     */
    public function rollback(string $version): void
    {
        $migrations = $this->discoverMigrations();

        if (!isset($migrations[$version])) {
            throw new \RuntimeException("Migration {$version} not found");
        }

        $class = $migrations[$version];
        $instance = new $class();

        if (!method_exists($instance, 'down')) {
            throw new \RuntimeException("Migration {$class} has no down() method");
        }

        $instance->down();
        $this->markRolledBack($version);
    }

    private function getAppliedVersions(): array
    {
        $connection = \Bitrix\Main\Application::getConnection();
        $result = $connection->query('SELECT VERSION FROM project_migrations');

        $versions = [];
        while ($row = $result->fetch()) {
            $versions[] = $row['VERSION'];
        }

        return $versions;
    }

    private function discoverMigrations(): array
    {
        $files = glob($this->migrationsDir . '/Migration*.php');
        $migrations = [];

        foreach ($files as $file) {
            $class = basename($file, '.php');

            if (!class_exists($class)) {
                require_once $file;
            }

            $version = preg_replace('/^Migration(\d+).*$/', '$1', $class);
            $migrations[$version] = $class;
        }

        ksort($migrations);

        return $migrations;
    }

    private function markApplied(string $version): void
    {
        $connection = \Bitrix\Main\Application::getConnection();
        $helper = $connection->getSqlHelper();

        $connection->queryExecute(sprintf(
            "INSERT INTO project_migrations (VERSION, APPLIED_AT) VALUES ('%s', NOW())",
            $helper->forSql($version)
        ));
    }

    private function markRolledBack(string $version): void
    {
        $connection = \Bitrix\Main\Application::getConnection();
        $helper = $connection->getSqlHelper();

        $connection->queryExecute(sprintf(
            "DELETE FROM project_migrations WHERE VERSION = '%s'",
            $helper->forSql($version)
        ));
    }
}

Запуск из CLI-скрипта на этапе деплоя:

&lt;?php

require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

$runner = new MigrationRunner(__DIR__ . '/migrations');
$applied = $runner->run();

echo 'Applied migrations: ' . implode(', ', $applied) . PHP_EOL;

Плюсы: схема на всех окружениях одинаковая, легко откатить, видно историю изменений. Минусы: ядро Bitrix не использует миграции, и если ваши сущности пересекаются с ядровыми таблицами, можно поймать неожиданные конфликты. Миграции стоит применять только к своим таблицам.

Индексация MySQL для каталога от 100 000 товаров

Штатный фасетный индекс Bitrix перестаёт справляться при 6–8 активных фильтрах. Нужны ручные индексы. Для запросов с коррелированным EXISTS по IBLOCK_ELEMENT_ID порядок колонок: (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE_ENUM).

ALTER TABLE b_iblock_element_prop_m14
ADD INDEX idx_prop_m14_element_prop_enum (IBLOCK_ELEMENT_ID, IBLOCK_PROPERTY_ID, VALUE_ENUM),
ALGORITHM=INPLACE, LOCK=NONE;

Плюсы: ускорение конкретных тяжёлых запросов в разы, полный контроль. Минусы: каждая лишняя колонка в индексе замедляет вставку и увеличивает размер БД, индексы не создают «на всякий случай» — только под конкретный запрос после EXPLAIN. На production ALTER TABLE выполняется с ALGORITHM=INPLACE, LOCK=NONE.

Очереди: таблица-очередь и сторонние брокеры

Тяжёлые операции не должны выполняться в момент запроса пользователя. Есть два уровня сложности, и каждый решает свой класс задач.

Таблица-очередь. Задачи складываются в свою таблицу project_queue, воркер раз в минуту читает пачку через SELECT ... FOR UPDATE SKIP LOCKED, обрабатывает и удаляет. Реализуется на чистом SQL и PHP, никаких внешних зависимостей. Хорошо работает до нескольких тысяч задач в час.

Важно: пример ниже — упрощённый. В продакшене нужны восстановление «зависших» задач по таймауту, лимит попыток, dead letter queue, идемпотентность обработчиков и валидация HANDLER по белому списку.

CREATE TABLE project_queue (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    HANDLER VARCHAR(255) NOT NULL,
    PAYLOAD TEXT NOT NULL,
    STATUS ENUM('new', 'in_progress', 'done', 'failed') DEFAULT 'new',
    ATTEMPTS INT DEFAULT 0,
    CREATED_AT DATETIME NOT NULL,
    UPDATED_AT DATETIME DEFAULT NULL,
    INDEX idx_status_created (STATUS, CREATED_AT)
);
// Постановка задачи
$connection = \Bitrix\Main\Application::getConnection();
$helper = $connection->getSqlHelper();

$connection->queryExecute(sprintf(
    "INSERT INTO project_queue (HANDLER, PAYLOAD, CREATED_AT) VALUES ('%s', '%s', NOW())",
    $helper->forSql($handler),
    $helper->forSql(json_encode($payload))
));
// Воркер, запускается через cron раз в минуту
$connection = \Bitrix\Main\Application::getConnection();
$connection->queryExecute("START TRANSACTION");

$result = $connection->query("
    SELECT ID, HANDLER, PAYLOAD
    FROM project_queue
    WHERE STATUS = 'new'
    ORDER BY ID
    LIMIT 100
    FOR UPDATE SKIP LOCKED
");

$tasks = [];
while ($row = $result->fetch()) {
    $tasks[] = $row;
}

if ($tasks) {
    $ids = array_column($tasks, 'ID');
    $connection->queryExecute(
        "UPDATE project_queue SET STATUS = 'in_progress' WHERE ID IN (" . implode(',', $ids) . ")"
    );
}

$connection->queryExecute("COMMIT");

foreach ($tasks as $task) {
    try {
        $handler = $task['HANDLER'];
        $payload = json_decode($task['PAYLOAD'], true);
        call_user_func($handler, $payload);

        $connection->queryExecute("DELETE FROM project_queue WHERE ID = " . (int)$task['ID']);
    } catch (\Throwable $e) {
        $connection->queryExecute(sprintf(
            "UPDATE project_queue SET STATUS = 'new', ATTEMPTS = ATTEMPTS + 1 WHERE ID = %d",
            (int)$task['ID']
        ));
    }
}

Плюсы таблицы-очереди: минимум инфраструктуры, полный контроль, легко отлаживать. Минусы: не масштабируется горизонтально, нет приоритетов, нет dead letter queue, на высоких нагрузках таблица становится узким местом.

Сторонние брокеры. Bitrix не имеет стабильного публичного API для промышленных очередей. В ядре есть пространство имён Bitrix\Main\Messenger, но оно относится к внутренним механизмам фреймворка, плохо документировано и может меняться между версиями. Использовать его в продакшене на 2026 год — рискованно.

Для высоконагруженных проектов промышленный стандарт — Symfony Messenger с транспортом RabbitMQ или Redis. Есть готовые модули, которые интегрируют его в Bitrix без переписывания ядра. Конкретные пакеты и их актуальность нужно проверять на момент внедрения: экосистема сторонних модулей для Bitrix меняется, и не все решения поддерживают PHP 8.2/8.3 и текущие релизы ядра.

Плюсы сторонних брокеров: промышленная надёжность, масштабирование, приоритеты, dead letter queue, отложенные сообщения. Минусы: дополнительная инфраструктура, нужно понимать AMQP, нужен Supervisor для воркеров, нужен мониторинг очередей. Для проектов с десятками тысяч задач в час RabbitMQ оправдан; для небольших проектов хватает таблицы-очереди.

Часть 3. Вёрстка и шаблонизация

Архитектура local/templates

Шаблон сайта — это не место для бизнес-логики. В header.php только подключение стилей, вывод шапки и открытие контейнера. Если в header.php появился вызов CIBlockElement::GetList — это ошибка. Данные готовятся в компонентах, шаблон только отображает. Стили разбиваются по компонентам, подключаются через Asset::addCss() в component_epilog.php.

Fluid-вёрстка и Container Queries

Вместо сотен @media — clamp() для типографики и отступов, Container Queries для изоляции стилей. Карточка товара в сетке каталога и в слайдере — один компонент, адаптируется к ширине родителя. Контейнер ставится на обёртку каждой карточки, а не на общую сетку.

.product-card {
    container-type: inline-size;
    container-name: product-card;
}

@container product-card (min-width: 400px) {
    .product-card__inner {
        flex-direction: row;
    }
}

Плюсы: компоненты переиспользуются без правок, нет JS-костылей для измерения ширины блока, меньше медиа-запросов. Минусы: поддержка Container Queries только в современных браузерах (95%+ на 2026 год), старые браузеры получат фиксированную вёрстку. Для проектов на Битрикс с B2B-аудиторией, где ещё встречаются устаревшие браузеры, требуется progressive enhancement.

Шаблонизаторы: Twig в Битриксе

Bitrix поддерживает сторонние шаблонизаторы только для шаблонов компонентов. Подключение Twig через arCustomTemplateEngines.

Плюсы: лаконичный синтаксис, явное разделение логики и отображения, защита от случайного вызова Bitrix API. Минусы: дополнительный слой абстракции, чуть ниже производительность, разработчикам нужно учить синтаксис. Для команды из нескольких разработчиков Twig оправдан; для одного разработчика нативный template.php проще.

Часть 4. Качество кода

PHPStan: статический анализ

parameters:
    level: 5
    paths:
        - local/lib
    scanDirectories:
        - bitrix/modules
    ignoreErrors:
        - '#Call to an undefined method Bitrix\\Main\\Entity\\DataManager::#'

Плюсы: ловит ошибки до запуска, помогает в рефакторинге. Минусы: на Bitrix много ложных срабатываний из-за динамических методов, часть ошибок приходится игнорировать. Уровень 5 — разумный компромисс между пользой и шумом.

PHP-CS-Fixer и EditorConfig

PHP-CS-Fixer приводит код к единому стилю через .php-cs-fixer.php. EditorConfig настраивает отступы на уровне редактора. Плюсы: единый стиль, меньше споров в ревью, чистая история diff. Минусы: автозапуск на CI может «дёргать» чужие коммиты, лучше запускать через pre-commit hook.

Тесты: PHPUnit и Codeception

class OrderServiceTest extends BitrixTestCase
{
    public function testCreateOrder(): void
    {
        $service = new OrderService();
        $result = $service->create(['productId' => 1, 'quantity' => 2]);

        $this->assertInstanceOf(Order::class, $result);
    }
}

Важно: BitrixTestCase — не встроенный класс Битрикс. Обычно он берётся из сторонних пакетов, например webarchitect609/bitrix-taxidermist, и требует отдельной настройки. Проверьте актуальность пакета под вашу версию PHP и ядра.

Плюсы: регрессия закрыта, рефакторинг безопасен, документация через тесты. Минусы: Bitrix плохо изолируется для юнит-тестов, приходится использовать сторонние решения, что усложняет настройку. Для небольших проектов полноценное покрытие тестами часто нерентабельно.

Часть 5. Мониторинг и логирование

Grafana + Prometheus + Sentry

Мониторинг должен показывать не только «железо», но и бизнес-метрики: TTFB, количество запросов, ошибки. Grafana и Prometheus дают единый дашборд. Sentry ловит исключения в реальном времени.

Плюсы: единая точка правды, история изменений, алерты, быстрая диагностика. Минусы: инфраструктура требует отдельного сервера, настройка занимает время. Для небольших проектов часто хватает Sentry и встроенных метрик.

Monolog: логирование в Битрикс

$logger = new \Monolog\Logger('app');
$logger->pushHandler(new \Monolog\Handler\RotatingFileHandler(
    $_SERVER['DOCUMENT_ROOT'] . '/local/logs/app.log',
    30,
    \Monolog\Logger::INFO
));

$logger->info('Order created', ['orderId' => $orderId]);

Плюсы: структурированные логи, ротация, разные каналы. Минусы: если писать лог в файл на каждой операции, диск заполнится за неделю. Нужны ротация, лимиты и Sentry для ошибок.

Часть 6. Безопасность

SQL-инъекции, XSS, CSRF

Всегда используйте SqlHelper::forSql() или параметризованные запросы. Для числовых — приведение к int. Все данные в шаблоне — через htmlspecialcharsbx(). В формах — bitrix_sessid_post(), на приёме — check_bitrix_sessid().

CSP и HTTP-заголовки безопасности

Content Security Policy для Bitrix нельзя включать «в лоб» с unsafe-inline и unsafe-eval — это не CSP, а его имитация. Ядро и большинство модулей Bitrix используют inline-скрипты и динамическую генерацию кода, поэтому жёсткая политика ломает админку и часть публичных страниц.

Правильный подход — начать с режима Content-Security-Policy-Report-Only, собрать отчёты о том, какие источники и inline-скрипты реально используются, и только потом включать боевой заголовок с nonce или хешами для inline-кода. Для приёма отчётов используйте report-to (современная замена устаревающего report-uri) и отдельный endpoint. На практике для Bitrix часто ограничиваются frame-ancestors 'self' и upgrade-insecure-requests, а полный CSP выносят в отдельную задачу.

# Отдельные заголовки, которые безопасны для Bitrix из коробки
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";

# CSP в режиме отчётов, без блокировки
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-to csp-endpoint";

Плюсы: защита от XSS, clickjacking, утечки через реферрер. Минусы: жёсткий CSP ломает часть модулей Bitrix — придётся разрешать конкретные внешние домены, а это ослабляет защиту. Настраивается аккуратно, тестируется в режиме report-only перед включением.

Cookies с флагами HttpOnly, Secure, SameSite

Кука сессии Bitrix должна иметь флаги HttpOnly, Secure и SameSite=Lax или Strict. Без них интернет-магазин на Битрикс уязвим к перехвату сессии. Настраивается в php.ini через session.cookie_httponly и session.cookie_secure.

Права на файлы, закрытый /bitrix

Базовые права: 644 для файлов, 755 для папок. Каталоги, в которые должен писать веб-сервер (/upload, /bitrix/cache, /bitrix/managed_cache, /bitrix/html_pages, /local/logs), требуют отдельной настройки владельца и прав — обычно их владельцем становится пользователь www-data или nginx. Файл dbconn.php должен быть недоступен извне.

Закрывать /bitrix целиком нельзя — сломается отдача статики (/bitrix/js, /bitrix/css, /bitrix/images, /bitrix/templates). Правильный подход: запретить выполнение PHP внутри /bitrix, кроме разрешённых точек (/bitrix/admin, /bitrix/urlrewrite.php, некоторые служебные скрипты), а статику оставить доступной.

# Запрет выполнения PHP в /bitrix, кроме разрешённых точек
location ~ ^/bitrix/(?!admin|urlrewrite\.php|tools/).*\.php$ {
    deny all;
    return 403;
}

# Отдача статики из /bitrix
location ~* ^/bitrix/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
    expires 30d;
    access_log off;
}

Часть 7. SEO

ЧПУ, модуль search

ЧПУ настраивается через urlrewrite.php и правила в компонентах. Модуль search отвечает за индексацию и полнотекстовый поиск. Плюс: правильные ЧПУ закладываются сразу. Минус: менять их потом больно, все ссылки окажутся битыми.

sitemap.xml и robots.txt

sitemap.xml генерируется модулем search или сторонними решениями, разбивается на файлы по 50 000 URL. robots.txt закрывает технические разделы и открывает каталог.

Микроразметка Schema.org

Для JSON-LD нельзя использовать htmlspecialcharsbx(): он превращает кавычки и спецсимволы в HTML-сущности, из-за чего JSON становится невалидным или искажённым. Используйте json_encode():

&lt;?php
$schema = [
    '@context' => 'https://schema.org',
    '@type' => 'Product',
    'name' => $arResult['NAME'],
    'offers' => [
        '@type' => 'Offer',
        'price' => $arResult['PRICE'],
        'priceCurrency' => 'RUB',
    ],
];
?&gt;
&lt;script type="application/ld+json"&gt;
&lt;?= json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?&gt;
&lt;/script&gt;

Плюсы: улучшает сниппеты, повышает CTR. Минусы: ошибки в разметке ловятся через Google Search Console уже после публикации. Правила Schema.org для Product регулярно меняются.

Часть 8. Интеграции: 1С и современные CRM

Для интернет-магазина на Битрикс интеграции — это половина ценности. Без обмена с 1С каталог и остатки будут расходиться с реальностью; без CRM теряется работа с клиентской базой, воронка продаж и маркетинг. Ниже — базовые сценарии, которые встречаются почти в каждом проекте.

Интеграция с 1С: CommerceML, REST API, промежуточная шина

Три сценария обмена с 1С: УТ, ERP, КА:

CommerceML — штатный механизм Bitrix. Выгружает каталог, цены, остатки, заказы через exchange1c.
Плюсы: работает из коробки, документация, поддержка вендора.
Минусы: медленный на больших каталогах, обмен по расписанию (не real-time), плохо переваривает сложные структуры свойств и торговых предложений, кастомизация формата ограничена.

REST API 1С (через http-сервисы или OData).
Плюсы: гибкость, можно запрашивать только нужные данные, real-time обмен остатками, легко подключить к очередям.
Минусы: требует доработки на стороне 1С (не во всех конфигурациях есть готовые сервисы), нужен стабильный канал, нужен middleware, если систем больше двух.

Промежуточная шина (RabbitMQ, Kafka, 1С:Шина).
Плюсы: масштабируется, развязывает системы, гарантирует доставку, легко добавлять новых потребителей.
Минусы: дорого по инфраструктуре, требует команды, которая умеет это поддерживать. Оправдано только для больших проектов с несколькими системами.

На этапе проектирования важно определить мастер-данные: цены и остатки — в 1С, контент — на сайте, заказы — на сайте, выгружаются в 1С. Если это не зафиксировать, через год каталог придётся переписывать.

Битрикс24: CRM и портал для команды

Битрикс24 — это и CRM, и корпоративный портал, и генератор лидов, и хранилище сделок. Интеграция с сайтом на Битрикс обычно делается через REST API и вебхуки.

Что даёт: лиды с форм сайта попадают в CRM автоматически, сделки синхронизируются с заказами, клиентская база объединяется с историей покупок, воронка строится по фактическим заказам, сквозная аналитика от рекламы до выручки.

Плюсы: родная интеграция с Bitrix, единая экосистема, готовые REST-методы, встроенный телефон и почта, не нужно ставить отдельный сервер. Минусы: тарифы растут с числом пользователей, часть интеграций требует «коробочной» версии, кастомизация ограничена рамками платформы. Для проектов, где команда уже работает в Битрикс24, интеграция окупается быстро.

RetailCRM: специализированная CRM для e-commerce

RetailCRM — CRM, заточенная под интернет-магазины и омниканальную торговлю. Работает с заказами, складом, доставкой, маркетингом.

Что даёт: единая карточка клиента со всеми заказами, интеграция с десятками служб доставки и платёжных систем, автоматизация триггерных рассылок, программа лояльности, сквозная аналитика, API с лимитами под нагрузку интернет-магазина.

Плюсы: заточена под e-commerce, интеграция с Bitrix через готовый модуль, много готовых сценариев автоматизации, поддержка СМС, email, мессенджеров, абонентская плата не завязана на число пользователей. Минусы: не заменяет корпоративный портал, ограниченные возможности по не-commerce процессам, чуть менее гибкая кастомизация, чем у Битрикс24. Для среднего интернет-магазина на Битрикс с потоком заказов от 100 в день RetailCRM окупается за счёт автоматизации.

AmoCRM: воронка продаж и лидогенерация

AmoCRM — CRM с сильной воронкой продаж, популярна в B2B и услугах. Интеграция с сайтом через REST API и вебхуки, есть готовые модули для Bitrix.

Что даёт: гибкая воронка с автоматизацией, работа с лидами из разных источников, цифровая воронка с триггерами, интеграция с телефонией, отчёты по конверсии на каждом этапе.

Плюсы: одна из лучших воронок на рынке, много готовых интеграций, гибкие цифровые воронки, широкая партнёрская сеть внедренцев. Минусы: оплата за пользователя, ограничения по числу сделок на тарифах, для интернет-магазина с большим потоком заказов тарифы быстро становятся дорогими. AmoCRM оправдана в проектах, где продажи идут через менеджеров, а не через корзину: B2B, услуги, сложные продукты.

Какую CRM выбрать

  • Битрикс24 — если команда уже работает в экосистеме Битрикс, нужен и портал, и CRM, и учёт в одном месте.
  • RetailCRM — если это интернет-магазин с потоком заказов, важны интеграции с доставкой, маркетинг, программы лояльности.
  • AmoCRM — если продажи идут через менеджеров, длинный цикл сделки, важен B2B и услуги.

Во всех трёх случаях интеграция с сайтом на Битрикс строится через REST API. Заказы и лиды передаются в CRM, статусы и оплаты возвращаются обратно, история покупок подтягивается в карточку клиента. Это стандартный паттерн, который стоит закладывать на этапе проектирования, а не после запуска.

Часть 9. Практика

Что чаще всего ломается при внедрении

Первое — композитный кэш. Включают, но в Nginx не добавляют блок отдачи — эффекта нет. Второе — очереди: ставят сторонний брокер, но забывают про Supervisor, воркеры падают при первом сбое. Третье — миграции: на staging применяют вручную, на production забывают, схема расходится. Четвёртое — CSP: включают жёстко с unsafe-inline, думают, что защитились, а по факту это не CSP. Пятое — бэкапы на тот же диск, где лежит сайт. Шестое — интеграция с CRM без очереди: при скачке заказов API отваливается по лимитам, заказы теряются. Седьмое — rsync --delete без исключений на первом же деплое сносит /bitrix и /upload. Восьмое — забывают про client_max_body_size, и загрузка файлов через админку молча падает на 4 МБ.

Как проверить, что всё работает

Прогон через Монитор качества Bitrix — обязательный минимум. Проверяются веб-окружение, интеграция дизайна, безопасность, производительность, размещение на хостинге. Отдельно проверяется, что агенты запускаются через cron, а не на хитах, что /bitrix не в Git, что в dbconn.php не лежат боевые пароли. Интеграции тестируются на реальных данных: пробный заказ идёт в CRM, синхронизация возвращает статус, очередь не теряет сообщения при перезапуске воркера.

Резюме и чек-лист перед запуском

Разработка на Битрикс без легаси — это про инфраструктуру, которая позволяет развивать проект годами. Сервер на чистом стеке, Docker, Git только с проектным кодом, Composer, D7 ORM и Highload-блоки, ручные индексы, Fluid-вёрстка, интеграции с 1С и CRM, агенты на cron, очереди, CI/CD, тесты, мониторинг, безопасность, SEO.

  • Инфраструктура: чистый стек Nginx + PHP-FPM 8.2/8.3 + Percona; композит отдаётся через Nginx; /bitrix/html_pages/ закрыт от прямого доступа; client_max_body_size поднят до 128 МБ; статика кэшируется.
  • Docker: docker-compose.yml для локальной разработки; отдельный docker-compose.prod.yml для production.
  • Git: только /local, конфиги и composer.json; ядро и /upload в .gitignore; .env не коммитится.
  • Branching: master для production, develop для staging, feature/* для задач.
  • CI/CD: пайплайн build, test, deploy; rsync по SSH с исключениями /bitrix, /upload, .env.
  • Backup: ежедневный mysqldump с --single-transaction; копия файлов; хранение 7–30 дней на отдельном сервере.
  • База данных: Highload-блоки для плоских справочников; DataManager для таблиц с составными индексами; миграции через MigrationRunner с таблицей версий.
  • Очереди: таблица-очередь для простых задач; сторонний брокер (Symfony Messenger + RabbitMQ) для высоких нагрузок; воркеры под Supervisor.
  • Вёрстка: clamp() и Container Queries; контейнер на обёртке каждой карточки.
  • Качество кода: PHPStan, PHP-CS-Fixer, EditorConfig; тесты через PHPUnit и Codeception.
  • Мониторинг: Grafana + Prometheus, Sentry, Monolog.
  • Безопасность: экранирование ввода, bitrix_sessid_post(), CSP в режиме отчётов, флаги HttpOnly/Secure/SameSite, закрытый /bitrix от выполнения PHP.
  • SEO: ЧПУ, sitemap.xml, robots.txt, Schema.org через json_encode().
  • Интеграции: 1С через CommerceML или REST API; CRM (Битрикс24, RetailCRM, AmoCRM) через REST API и вебхуки; очереди для устойчивости обмена.
  • Монитор качества: обязательные тесты пройдены; критические ошибки безопасности устранены.

Материал получился обзорным — каждая тема заслуживает отдельной статьи. Дальше решать вам: углублять конкретное направление, собирать по нему полноценный инженерный гайд или оставить как краткий ориентир при развёртывании Битрикс-проектов.

Александр Тихий
Автор статьи

Александр Тихий

Fullstack-разработчик · 1С-Битрикс

Разрабатываю и развиваю интернет-магазины и корпоративные порталы на 1С-Битрикс. Интеграции с 1С, highload-нагрузки, безопасность по 152-ФЗ.


Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Напишите мне, чтобы обсудить задачу. Работаю удаленно, официально (самозанятый), стоимость часа — 1800 ₽, в день могу уделять проекту 3–4 часа. Отвечаю быстро, консультация бесплатная.

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта