Оптимизация количества HTTP-запросов 1С-Битрикс
На аудите Битрикс-проектов регулярно встречается страница с 180–250 HTTP-запросами при загрузке. Это не преувеличение: каждый компонент может добавить 2–4 CSS-файла и 3–5 JS-файлов, плюс иконки как отдельные PNG, плюс трекеры аналитики, плюс виджеты. Каждый запрос — это DNS, TCP, TLS, заголовки ответа. При HTTP/1.1 браузер держит 6 параллельных соединений на домен. При HTTP/2 мультиплексирование помогает, но не устраняет накладные расходы полностью.
Аудит текущего состояния
Первый шаг — замерить, не угадывать. Инструменты:
- Chrome DevTools → Network: колонки Requests, Transferred, DOMContentLoaded, Load
- WebPageTest (webpagetest.org): Waterfall-диаграмма с группировкой по типам
- Lighthouse: метрика «Serve static assets with an efficient cache policy» + «Avoid chaining critical requests»
Смотрим на водопаде: где самые длинные цепочки зависимостей? Обычно картина такая:
HTML → CSS (×5) → шрифты (×6) → JS (×8) → изображения (×40+) → Ajax-запросы компонентов (×3-5)
CSS и JS: комбайнер и бандлинг
Встроенный комбайнер Битрикс
В настройках главного модуля (/bitrix/admin/settings.php?lang=ru) есть «Объединять CSS-файлы» и «Объединять JS-файлы». Комбайнер объединяет файлы в один запрос /bitrix/cache/css/[hash].css. Он работает, но есть нюансы:
- Объединяет только файлы из
AddCSS()/AddHeadScript(), но не inline-стили компонентов - При инвалидации кэша (правка любого файла) hash меняется — браузеры скачивают заново
- Не минифицирует CSS/JS — только конкатенация
Webpack/Vite для кастомных ресурсов
Для собственного кода (не ядра Битрикс) настраиваем бандлер:
// vite.config.js
export default {
build: {
rollupOptions: {
input: {
main: 'local/templates/main/src/main.js',
catalog: 'local/templates/main/src/catalog.js',
}
}
}
}
Получаем 2 бандла вместо 15+ отдельных файлов. Разделение на main и catalog важно: не грузим JS каталога на статических страницах.
Иконки: спрайты и inline SVG
Каждая иконка как отдельный файл — самый быстрый способ получить 30–50 лишних запросов. Варианты:
SVG-спрайт — один файл со всеми иконками:
<!-- sprite.svg -->
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-cart" viewBox="0 0 24 24">...</symbol>
<symbol id="icon-search" viewBox="0 0 24 24">...</symbol>
</svg>
<!-- использование -->
<svg><use href="/local/templates/main/img/sprite.svg#icon-cart"></use></svg>
Один HTTP-запрос для всей иконографии сайта. Кэшируется надолго.
Inline SVG через PHP-хелпер для иконок первого экрана:
function svg(string $name): string {
static $cache = [];
if (!isset($cache[$name])) {
$path = __DIR__ . '/icons/' . $name . '.svg';
$cache[$name] = file_exists($path) ? file_get_contents($path) : '';
}
return $cache[$name];
}
Inline SVG = 0 HTTP-запросов, но увеличивает размер HTML.
Ajax-запросы компонентов
Битрикс-компоненты с 'AJAX_MODE' => 'Y' делают отдельный XHR при переходе между страницами каталога. Это нормально, но при инициализации страницы часто видим несколько параллельных Ajax-запросов к ajax.php с разными параметрами. Решение — batching: объединить несколько запросов в один через очередь:
// Накапливаем запросы за 50 мс, затем отправляем batch
const queue = [];
function batchRequest(params) {
queue.push(params);
if (queue.length === 1) {
setTimeout(() => {
const batch = [...queue];
queue.length = 0;
fetch('/api/batch', {
method: 'POST',
body: JSON.stringify(batch)
});
}, 50);
}
}
На стороне сервера — endpoint /api/batch, который диспетчеризует запросы и возвращает массив ответов.
Изображения: lazy loading и sprites
Изображения в каталоге — крупнейший источник запросов. Обязательный минимум:
// В шаблоне компонента catalog.element
echo '<img src="' . $arItem['PREVIEW_PICTURE']['SRC'] . '"
loading="lazy"
width="' . $arItem['PREVIEW_PICTURE']['WIDTH'] . '"
height="' . $arItem['PREVIEW_PICTURE']['HEIGHT'] . '"
alt="' . htmlspecialchars($arItem['NAME']) . '">';
loading="lazy" — нативный lazy loading. Браузер не запрашивает изображения ниже viewport до скролла. На странице каталога с 48 карточками это убирает 30–40 запросов из критического пути.
Кейс: оптимизация маркетплейса
Онлайн-магазин электроники на Битрикс «Электронная торговля»: главная страница — 214 HTTP-запросов, Load time 8,3 с.
Что сделали по шагам:
- Включили CSS/JS комбайнер → -18 запросов
- Собрали SVG-спрайт из 64 иконок → -63 запроса
- Добавили
loading="lazy"всем изображениям ниже fold → -41 запрос из критического пути - Перенесли Google Analytics и Яндекс.Метрику на
defer→ убрали из блокирующего пути - Объединили 5 кастомных JS-файлов через Vite в 1 бандл → -4 запроса
Итог: 214 → 88 запросов, Load time: 8,3 с → 3,1 с, LCP: 5,2 с → 1,9 с.
HTTP/2 Push и preload
При HTTP/2 можно анонсировать ресурсы через Link: <url>; rel=preload в заголовке ответа. В Nginx:
location = / {
add_header Link "</local/templates/main/fonts/roboto-400.woff2>; rel=preload; as=font; crossorigin";
add_header Link "</local/templates/main/css/main.css>; rel=preload; as=style";
}
Это не уменьшает число запросов, но уменьшает водопад — браузер узнаёт о ресурсах раньше.
Сроки
| Масштаб | Состав | Срок |
|---|---|---|
| Базовый | Комбайнер, lazy loading, defer трекеров | 1–2 дня |
| Средний | SVG-спрайт, Vite-бандлинг кастомного кода, HTTP/2 | 4–7 дней |
| Полный | Batch API для Ajax, полный аудит и устранение всех избыточных запросов | 8–14 дней |







