Налаштування асинхронного завантаження JS для 1С-Бітрікс
Найпоширеніший симптом: Lighthouse показує «Eliminate render-blocking resources», у списку — jQuery, Swiper, компонентні скрипти Бітрікс. Браузер парсить HTML, зустрічає <script src="..."> без атрибутів і зупиняє рендер до завантаження та виконання файлу. На типовому Бітрікс-сайті таких блокуючих скриптів набирається 5–10.
Механізм керування JS у Бітрікс
Бітрікс реєструє скрипти через CMain::AddHeadScript() і Asset::getInstance()->addJs(). Метод ShowHead() виводить їх у <head> без defer/async. Компоненти додають скрипти через $APPLICATION->AddHeadScript() — те саме. Перевизначити поведінку можна лише на рівні шаблону або через постобробку буфера.
Додавання defer/async через шаблон
Найбезпечніший спосіб — використовувати подію OnEndBufferContent для постобробки підсумкового HTML:
// local/php_interface/init.php
AddEventHandler('main', 'OnEndBufferContent', 'deferScripts');
function deferScripts(string &$content): void
{
// Додаємо defer всім зовнішнім скриптам, крім явно виключених
$exclude = ['jquery.min.js', '/bitrix/js/main/core/core.js'];
$content = preg_replace_callback(
'/<script\s([^>]*src=["\'][^"\']+["\'][^>]*)>/i',
function (array $m) use ($exclude): string {
foreach ($exclude as $ex) {
if (str_contains($m[0], $ex)) {
return $m[0];
}
}
if (str_contains($m[1], 'defer') || str_contains($m[1], 'async')) {
return $m[0];
}
return '<script ' . $m[1] . ' defer>';
},
$content
);
}
jQuery і core.js Бітрікса виключаємо з defer — від них залежить ініціалізація компонентів. Все інше отримує defer.
Asset Manager і групи залежностей
У Бітрікс 14+ працює \Bitrix\Main\Page\Asset. Скрипти можна реєструвати із зазначенням позиції:
\Bitrix\Main\Page\Asset::getInstance()->addJs(
'/local/js/mymodule.js',
false, // не об'єднувати
\Bitrix\Main\Page\Asset::POS_AFTER // після </body>
);
POS_AFTER розміщує скрипт перед </body> — де-факто аналог defer для незалежних модулів. Для скриптів, які потрібні в DOM-ready, це краще за async.
Коли не можна використовувати defer
Скрипти, які не можна відкладати без наслідків:
- jQuery, якщо інші скрипти в тілі сторінки викликають
$()inline -
core.jsБітрікса таajax.js— ядро BX - Лічильники аналітики, якщо вони вимірюють час до інтерактивності
- Скрипти A/B-тестування (змінюють DOM до рендера)
Для них використовуємо <link rel="preload" as="script"> — браузер завантажує файл з високим пріоритетом, але виконання відбувається в порядку, контрольованому розробником.
Кейс: сайт туристичної компанії
Сайт на Бітрікс «Старт» з пошуковою формою на головній. TBT (Total Blocking Time) у Lighthouse — 1 840 мс. Причина: 12 скриптів у <head>, включаючи Swiper 8.1 (120 КБ), Fancybox (80 КБ), карта Яндекс (асинхронний API, але блокуюча ініціалізація).
Після додавання defer через OnEndBufferContent і перенесення карти на відкладену ініціалізацію через IntersectionObserver:
- TBT: 1 840 мс → 240 мс
- TTI (Time to Interactive): 6,1 с → 2,8 с
- Lighthouse Performance score: 34 → 78
Роботи — 1 день.







