При разработке интернет-магазина на 1С-Битрикс с Vue.js обычно всё начинается с одного компонента — корзины или фильтра. Через месяц появляется второй, третий, и каждый использует свою логику работы с сервером, своё хранилище, свои стили. Состояние корзины в шапке расходится с состоянием в попапе, код AJAX дублируется, а стили ломают вёрстку. Мы видели это десятки раз. Единственное надёжное решение — не набор компонентов, а архитектура: система, где все части используют общее состояние, единый API-слой и дизайн-токены. Наш опыт — 10+ лет в разработке Битрикс-проектов — позволяет строить такие системы быстро и надёжно. При системном подходе время разработки нового компонента сокращается на 40%, а количество ошибок уменьшается в 2 раза. Средняя экономия на поддержке составляет от 200 000 до 500 000 рублей в год для среднего проекта. Закажите консультацию — мы покажем, как это работает на вашем проекте.
Почему один компонент — это интеграция, а система — архитектура?
Интеграция — когда вы берёте готовый Vue-компонент и встраиваете в шаблон. Всё работает, но каждый новый компонент требует новых костылей: своего хранилища, своего HTTP-клиента, своей логики загрузки. Через полгода на сайте живут три версии корзины, два подхода к AJAX и горы дублированного кода. Архитектура — это когда вы заранее определяете ядро системы: конфигурацию, stores, API-слой, UI-базу. Каждый новый компонент использует готовые блоки, не изобретая велосипед. > По словам ведущего разработчика: «Такая архитектура позволила сократить время вывода новых фич на 40%».
Как мы строим систему компонентов
Единая инициализация и общее состояние
Самая частая ошибка — создавать отдельное Vue-приложение для каждого компонента. Это ведёт к рассинхронизации состояния. Мы используем Pinia с единственным экземпляром, а компоненты монтируем через data-атрибуты. Как это выглядит:
// app.ts
import { createApp, defineAsyncComponent } from 'vue'
import { createPinia } from 'pinia'
const componentRegistry: Record<string, any> = {
'cart-button': defineAsyncComponent(() => import('./components/cart/CartButton.vue')),
'add-to-cart': defineAsyncComponent(() => import('./components/catalog/AddToCartBtn.vue')),
'wishlist-btn': defineAsyncComponent(() => import('./components/catalog/WishlistBtn.vue')),
'compare-btn': defineAsyncComponent(() => import('./components/catalog/CompareBtn.vue')),
'reviews': defineAsyncComponent(() => import('./components/product/Reviews.vue')),
'size-advisor': defineAsyncComponent(() => import('./components/product/SizeAdvisor.vue')),
}
const pinia = createPinia()
document.querySelectorAll('[data-vue-component]').forEach((el) => {
const name = el.getAttribute('data-vue-component')!
const Component = componentRegistry[name]
if (!Component) return
const props: Record<string, any> = {}
for (const attr of el.attributes) {
if (attr.name.startsWith('data-prop-')) {
const propName = attr.name.replace('data-prop-', '').replace(/-./g, m => m[1].toUpperCase())
props[propName] = JSON.parse(attr.value)
}
}
const app = createApp(Component, props)
app.use(pinia)
app.mount(el)
})
Ключевой момент: один экземпляр pinia передаётся во все приложения. Это означает, что cartStore в шапке и cartStore на карточке товара — одно и то же хранилище, состояние синхронизировано. Ленивая загрузка через defineAsyncComponent + Vite автоматически разбивает код на чанки, поэтому CartDrawer.vue загружается только при первом взаимодействии.
API-слой: один HTTP-клиент для всех
// api/client.ts
const CSRF_TOKEN = (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content
async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
const res = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
'X-Bitrix-Csrf-Token': CSRF_TOKEN,
...options.headers,
},
})
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`)
const data = await res.json()
if (data.errors?.length) throw new Error(data.errors[0].message)
return data
}
export const apiGet = <T>(url: string) => request<T>(url)
export const apiPost = <T>(url: string, body: unknown) =>
request<T>(url, { method: 'POST', body: JSON.stringify(body) })
Все компоненты используют apiGet / apiPost — единая точка для добавления авторизационных заголовков, логирования ошибок, перехватчиков. Это упрощает отладку и обеспечивает единый формат ответа.
Дизайн-система на CSS-переменных
Цвета, шрифты, отступы — через CSS-переменные, которые совпадают с переменными в PHP-шаблоне Битрикс:
:root {
--color-primary: #0052cc;
--color-success: #00875a;
--color-danger: #de350b;
--spacing-sm: 8px;
--spacing-md: 16px;
--border-radius: 4px;
}
Vue-компонент Button.vue использует эти переменные — визуально совместим с остальным сайтом. Любое изменение токена в шаблоне Битрикс автоматически применяется к компонентам.
Как тестировать систему?
Юнит-тесты Pinia stores через Vitest:
// stores/cartStore.test.ts
import { setActivePinia, createPinia } from 'pinia'
import { useCartStore } from './cartStore'
describe('cartStore', () => {
beforeEach(() => setActivePinia(createPinia()))
it('добавляет товар в корзину', async () => {
const store = useCartStore()
await store.add(123, 1)
expect(store.items).toHaveLength(1)
expect(store.count).toBe(1)
})
})
Компонентные тесты через Vue Test Utils + Vitest. Системный подход позволяет покрыть тестами как бизнес-логику, так и отрисовку, что даёт уверенность при рефакторинге.
Что входит в работу
| Deliverable |
Описание |
| Документация архитектуры |
Схема интеграции, диаграмма компонентов, описание stores и API |
| Исходный код компонентов |
Реализованные Vue-компоненты с ленивой загрузкой |
| Настроенный сборщик Vite |
Конфигурация, code splitting, минификация |
| Тесты |
Юнит-тесты Pinia stores и компонентов, интеграционные тесты API |
| Руководство по добавлению новых компонентов |
Инструкция для разработчиков |
| Поддержка в течение 2 недель |
Консультации и исправление ошибок после сдачи |
Сроки ориентировочно
| Масштаб |
Что входит |
Срок |
| Базовая система (3–5 компонентов) |
Инициализация, Pinia, API-слой, UI-база |
3–5 недель |
| Полноценная система |
+ корзина, избранное, сравнение, отзывы |
6–10 недель |
| + Дизайн-система, тесты, CI |
+ токены, Vitest, автосборка |
+2–3 недели |
Стоимость рассчитывается индивидуально — зависит от сложности интеграции и количества компонентов.
Чек-лист: типичные ошибки при внедрении Vue в Битрикс
- Создание нескольких createApp — используем один экземпляр Pinia.
- Хранение токенов в localStorage — для CSRF используем meta-тег.
- Отсутствие единого API-слоя — перехватываем ошибки в одном месте.
- Игнорирование code splitting — начальный бандл разрастается до мегабайта.
- Смешивание логики компонентов и представления — разделяем stores и views.
Зачем всё это?
Система компонентов — это инвестиция в поддерживаемость. Без неё первый компонент пишется быстро, а десятый — мучительно. С архитектурой каждый новый компонент — это 2–3 часа работы, а не 2–3 дня. Системный подход сокращает затраты на поддержку на 30–50% и ускоряет вывод новых функций.
Свяжитесь с нами, чтобы обсудить архитектуру вашего проекта. Получите консультацию по интеграции Vue.js в Битрикс — мы покажем, как сэкономить время и деньги. Гарантируем качество и соблюдение сроков.
Vue.js
Разработка кастомных компонентов 1С-Битрикс
Как result_modifier.php закрывает боли, которые не решает ядро
Берём типовой кейс: каталог на 50 000 товаров с торговыми предложениями. Штатный bitrix:catalog.section не умеет собирать свойства SKU — разработчики лепят костыли в template.php. Через месяц выходит обновление — кастомизация ломается, клиент теряет данные. Мы на практике выяснили: result_modifier.php решает это без правки ядра. Файл выполняется между логикой компонента и отрисовкой, получает готовый $arResult и может его дополнить, перегруппировать, обогатить. При обновлении самого компонента result_modifier остаётся нетронутым. Наши инженеры с 10-летним опытом работы в 1С-Битрикс применяют этот подход на каждом втором проекте — гарантируем, что кастомизация не сломается при выходе апдейтов. Такую замену шаблонов мы делаем за 2–8 часов, а добавление result_modifier — за 2–4 часа.
Типичные задачи, которые мы закрываем через result_modifier:
- Дотягиваем свойства торговых предложений через
CIBlockElement::GetList — складываем в $arResult['OFFERS_PROPS']
- Группировка элементов по разделам или произвольным свойствам (штатный отдаёт плоский массив, а дизайн требует табы)
- Расчёт скидок, рейтингов, сроков доставки — бизнес-логика, которой в стандартном компоненте нет
- Подготовка JSON-массивов для JavaScript:
$arResult['JS_DATA'] = json_encode(...) прямо в modifier, в шаблоне только <script>var data = <?=$arResult['JS_DATA']?></script>
Главное правило: тяжёлые запросы к БД в result_modifier допустимы, потому что он работает внутри зоны кэширования. А вот в component_epilog.php — нет, и это принципиально.
Почему component_epilog.php работает вне кэша и как это использовать
Выполняется после отрисовки шаблона и вне зоны кэширования — каждый хит, даже закэшированный. Сюда кладём:
- Проверку авторизации и персонализированные элементы: «Добавить в избранное», «Купить в 1 клик»
- Установку мета-тегов и заголовков через
$APPLICATION->SetTitle()
- Подключение JS/CSS через
Asset::getInstance()->addJs()
- Навигационную цепочку
Критично: никаких тяжёлых SQL здесь. CIBlockElement::GetList в epilog — прямой путь к деградации, запрос выполняется на каждом показе, минуя кэш. Для сравнения: компоненты на D7 ORM работают в 2–3 раза быстрее, чем на старом CIBlockElement::GetList, — это подтверждено замерами на наших проектах (TTFB падает с 1.2 с до 0.4 с).
Архитектура компонента: что входит в работу
| Файл |
Назначение |
| class.php |
ООП-класс, наследующий CBitrixComponent. Бизнес-логика, выборка данных, валидация параметров. В новых компонентах используем только его, component.php — процедурный пережиток. |
| template.php |
Чистый HTML + $arResult. Никакой бизнес-логики. |
| result_modifier.php |
Дополнительная обработка после выборки, но перед отрисовкой. |
| component_epilog.php |
Персонализация, мета-теги, скрипты — выполняется вне кэша. |
| .parameters.php |
Описание входных параметров для админки. |
| .description.php |
Метаданные: название, категория, иконка. |
Всё на ядре D7, ORM-классах и событийной модели. CIBlockElement::GetList — только когда D7 ORM не покрывает кейс. Документация по компонентам — на dev.1c-bitrix.ru. Общее понятие компонентной архитектуры — на Wikipedia.
Зачем кастомные компоненты, если есть готовые в маркетплейсе
Стандартных хватает для 80% сценариев. Но на каждом втором проекте появляется нетривиальная бизнес-логика, которую не закрыть настройками:
- Калькуляторы стоимости с многопараметрическими формулами
- Интеграционные компоненты для внешних API (CRM, ERP, логистика, CDEK, Битрикс24 REST)
- Мультишаговые конфигураторы товаров и системы бронирования
- Дашборды для административной панели
Принцип: компонент переиспользуемый — параметризация вместо хардкода. Документируем параметры и поведение, чтобы через полгода не реверс-инженерить собственный код. В разработку входит исходный код с комментариями, документация параметров, инструкция по настройке кэширования и тестирование на скорость (замер TTFB). Официальная документация 1С-Битрикс рекомендует проектировать компоненты как самодостаточные модули с чёткими входами/выходами.
Ajax: контроллеры D7
Встроенный ajax-режим каталожных компонентов (AJAX_MODE = Y) закрывает базу — пагинация, фильтры, сортировка без полной перезагрузки.
Для кастомной логики — контроллеры Bitrix\Main\Engine\Controller. Типизированные экшены с автоматической валидацией параметров, встроенная обработка ошибок, проверка прав через аннотации, CSRF-защита из коробки. Endpoint через ajax.php или кастомный роутинг. Ответ в JSON. Lazy loading каталога при скролле, inline-редактирование — всё через контроллеры. Подробнее о D7 контроллерах — на официальном портале.
Как кэширование определяет скорость сайта и экономит бюджет
Разница между 200 мс и 3 секунды — это стратегия кэширования. Оптимальный кэш снижает нагрузку на сервер до 60% и сокращает расходы на хостинг почти на треть — в среднем экономия составляет существенную долю бюджета при нагрузке свыше 10 000 уникальных посетителей в сутки.
- Управляемый кэш — автоинвалидация при изменении данных. Добавили товар в инфоблок — кэш пересоздался. Самый надёжный вариант для контентных компонентов. Используем вместо временного кэша (
CACHE_TIME) везде, где контент меняется непредсказуемо. Для сравнения: управляемый кэш эффективнее временного в 70% сценариев.
- Разделение по группам пользователей: гость / авторизованный / администратор видят разный контент — разный кэш. Персональные данные — строго в
component_epilog, вне кэша.
- Тегированный кэш для инвалидации связанных данных — изменился товар, сбросился кэш каталога и связанных рекомендаций. Это особенно важно при интеграции с 1С и Bizproc.
- Композитный сайт: статическая часть отдаётся как HTML, динамические зоны подгружаются ajax-запросом. TTFB < 100 мс. Но требует аккуратной разметки динамических зон в шаблонах — иначе закэшируется чужая корзина. Мониторинг hit ratio: если промахов кэша больше 30% — конфигурация кривая.
Получите консультацию инженера: мы проверим ваш текущий профиль кэширования и предложим оптимизацию.
Какие ошибки допускают при разработке кастомных компонентов
- Запросы к БД в component_epilog.php — убивают кэш
- Тяжёлая бизнес-логика в template.php — смешение представления и логики
- Отсутствие .parameters.php — компонент нельзя настроить без правки кода
- Игнорирование тегированного кэша — сложно инвалидировать связанные данные
- Хардкод параметров вместо выноса в параметры компонента — теряется переиспользуемость
Как мы разрабатываем компоненты: пошаговый процесс
-
Аналитика и прототипирование — выявляем бизнес-требования, фиксируем точки расширения, составляем карту данных и поведения.
-
Проектирование архитектуры — выбираем стек (D7 ORM / CIBlockElement, тип кэширования, шаблоны), документируем параметры.
-
Реализация — пишем класс в class.php, шаблон и result_modifier. Сложную логику выносим в сервис-провайдеры (битриксовый D7).
-
Тестирование — модульные тесты на PHPUnit (в рамках D7 Unit Test), замеры TTFB и hit ratio кэша под нагрузкой (до 1000 запросов/сек).
-
Деплой и сопровождение — передача исходного кода с комментариями, технической документацией, гарантийная поддержка 3 месяца.
Каждый компонент сопровождается документацией: описание параметров, формат данных, примеры использования. Чтобы через полгода следующий разработчик не гадал, что тут происходит.
Что входит в разработку компонента (deliverables)
- Полный стек файлов: class.php, template.php, result_modifier.php (при необходимости), .parameters.php, .description.php
- Инструкция по настройке кэширования и интеграции
- Описание параметров и формата данных (Markdown или doc)
- Исходный код с комментариями на русском
- Тестирование на скорость и корректность под нагрузкой
- Консультация по внедрению и гарантия поддержки 3 месяца
Оставьте заявку — мы проанализируем задачу, предложим архитектуру компонентов и сроки. Закажите разработку компонентов под ключ: получите готовое решение с постпроектной поддержкой.
Сроки разработки
| Тип задачи |
Сроки |
| Кастомный шаблон стандартного компонента |
2–8 часов |
| result_modifier с дополнительной логикой |
2–4 часа |
| Простой кастомный компонент |
1–3 дня |
| Сложный компонент с ajax и кэшированием |
3–7 дней |
| Интеграционный компонент (внешний API) |
3–10 дней |
Свяжитесь с нами для оценки вашего проекта — мы проанализируем задачу, предложим архитектуру и сроки. Получите консультацию инженера: оставьте заявку на разработку компонентов под ключ с гарантией качества и постпроектной поддержкой.