Налаштування асинхронного завантаження JS для 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Налаштування асинхронного завантаження JS для 1С-Бітрікс
Проста
~1 робочий день
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • 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
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Налаштування асинхронного завантаження 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 день.