Расширения

Расширение — способ организации JS и CSS кода в 1С-Битрикс: Управление Сайтом и Битрикс24. Расширения помогают организовать код, обеспечивая его модульность и управляемость. Они позволяют объединять файлы JavaScript и CSS в бандлы, что упрощает их загрузку и использование в браузере. Бандлы — это объединенные файлы, которые помогают оптимизировать загрузку ресурсов.

Расположение расширений

Расширения, которые поставляются с продуктами 1С-Битрикс: Управление Сайтом и Битрикс24, расположены в директории bitrix. Клиентские расширения обычно размещаются в папке local.

  • /bitrix/js/<module>/<extension>/

  • /local/js/<module>/<extension>/

Структура

Пример структуры расширения myextension:

  • src — исходные файлы.

  • dist — бандлы для браузера.

  • bundle.config.js — конфигурационный файл для сборщика.

  • config.php — конфигурационный файл экстеншна.

  • lang — локализации.

  • test — тесты.

  • @types — файлы *.d.ts.

Обязательные элементы: src, dist, bundle.config.js, config.php.

Необязательные элементы: директории lang, test, @types.

Если у вас установлен консольный инструмент @bitrix/cli, то структуру расширения можно создать, выполнив команду bitrix create.

Директория src

В директории src размещаются исходные файлы в формате ES6. Из этих файлов на основании данных файла конфигурации и внутренних ссылок будут созданы финальные версии в формате ES5 — бандлы. Они используются для подключения в браузере.

Внутри файла можно использовать import других файлов из текущей директории или импортировать другие CoreJS расширения.

Для импорта переменных и классов из другого файла в текущей директории используйте следующий синтаксис:

  • если в папке src есть файл file.js с экспортируемым классом SomeClass

    import {SomeClass} from "./file";
    
  • для импорта file.css

    import './file.css';
    
  • для импорта CoreJS 2.0

    import {Loader} from 'main.loader';
    
  • для импорта библиотеки из CoreJS 1.0

    import "main.date";
    

Директория dist

В директории dist располагаются файлы, автоматически созданные с помощью сборщика для последующего подключения в браузере. Обычно это файлы <extension>.bundle.js и <extension>.bundle.css.

Файл bundle.config.js

Файл конфигурации сборщика.

  • Базовая конфигурация.

    module.exports = {
        input: './src/app.js',
        output: './dist/app.bundle.js',
    };
    

    В данном файле конфигурации не указываются файлы CSS. Их необходимо импортировать в файле, который указан в параметре input — точке входа сборки.

    // Файл из input — src/app.js
    import './style.css';  // импорт CSS
    
  • Все параметры.

    module.exports = {
        // Файл, для которого необходимо выполнить сборку.
        // Необходимо указать относительный путь
        input: string,
    
        // Путь к бандлу, который будет создан в результате сборки.
        // Обычно это ./dist/<extension_name>.bundle.js
        // Необходимо указать относительный путь
        output: string || {js: string, css: string},
    
        // Неймспейс, в который будут добавлены все экспорты из файла,
        // указанного в input. Например, 'BX.Main.Filter'
        namespace: string,
    
        // Списки файлов для принудительного объединения.
        // Файлы будут объединены без проверок на дублирование кода.
        // sourcemap's объединяются автоматически.
        // Необходимо указать относительные пути
        concat: {
            js: Array<string>,
            css: Array<string>,
        },
    
        // Разрешает или запрещает сборщику модифицировать config.php.
        // По умолчанию true (разрешено)
        adjustConfigPhp: boolean,
    
        // Разрешает или запрещает сборщику удалять неиспользуемый код.
        // По умолчанию true (включено)
        treeshake: boolean,
    
        // Разрешает или запрещает пересобирать бандлы,
        // если сборка запущена не в корне текущего расширения.
        // По умолчанию `false` (разрешено)
        'protected': boolean,
    
        plugins: {
            // Переопределяет параметры Babel.
            // Можно указать собственные параметры Babel
            // https://babeljs.io/docs/en/options
            // Если указать false, то код будет собран без транспиляции
            babel: boolean | Object,
    
            // Дополнительные плагины Rollup,
            // которые будут выполняться при сборке бандлов
            custom: Array<string | Function>,
        },
        // Определяет правила обработки путей к изображениям в CSS.
        // Доступно с версии 3.0.0
        cssImages: {
            // Определяет правило, по которому изображения должны
            // быть обработаны:
            // 'inline' — преобразует изображения в инлайн
            // 'copy' — копирует изображения в директорию 'output'
            // По умолчанию 'inline'
            type: 'inline' | 'copy',
            // Путь к директории, в которую должны быть скопированы
            // используемые изображения
            output: string,
            // Максимальный размер изображений в кб, которые могут быть
            // преобразованы в инлайн.
            // По умолчанию 14кб
            maxSize: number,
            // Использовать ли svgo для оптимизации svg.
            // По умолчанию true
            svgo: boolean,
        },
        resolveFilesImport: {
            // Путь к директории, в которую должны быть скопированы
            // импортированные изображения
            output: string,
    
            // Определяет разрешенные для импорта типы файлов.
            // По умолчанию ['**/*.svg', '**/*.png', '**/*.jpg', '**/*.gif']
            // https://github.com/isaacs/minimatch
            include: Array<string>,
            // По умолчанию []
            exclude: Array<string>,
        },
    
        // Определяет правила Browserslist:
        // false — не использовать (по умолчанию)
        // true — использовать файл .browserslist / .browserslistrc
        browserslist: boolean | string | Array<string>,
    
        // Включает или отключает минификацию.
        // По умолчанию отключено.
        // Может принимать объект настроек Terser:
        // false — не минифицировать (по умолчанию)
        // true — минифицировать с настройками по умолчанию
        // object — минифицировать с указанными настройками
        minification: boolean | object,
    
        // Включает или отключает преобразование нативных JS классов.
        // По умолчанию значение параметра выставляется автоматически
        // на основании browserslist
        transformClasses: boolean,
    
        // Включает или отключает создание Source Maps файлов
        sourceMaps: boolean,
    
        // Настройки тестов
        tests: {
            // Настройки локализации
            localization: {
                // Код языка локализации. По умолчанию 'en'
                languageId: string,
                // Включает или выключает автозагрузку фраз в тестах.
                // По умолчанию включено
                autoLoad: boolean,
            },
        },
    };
    

Файл config.php

Конфигурационный файл расширения config.php определяет, какие файлы необходимо подключить на странице.

При использовании @bitrix/cli файл config.php будет автоматически создан при сборке и будет обновляться по мере необходимости. Например, если в коде JS появится зависимость, которая не указана в config.php, она будет автоматически добавлена в rel.

  • Базовая конфигурация.

    <?php if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
    
    return [
        'css' => './dist/loader.bundle.css',
        'js' => './dist/loader.bundle.js',
        'rel' => [
            'main.core'
        ]
    ];
    
    
  • Все параметры.

    // ...
    return [
        // Путь к `css` файлу или массив путей
        // Рекомендуем указывать относительный путь
        'css' => String | Array<String>,
    
        // Путь к `js` файлу или массив путей к `js` файлам
        // Рекомендуем указывать относительный путь
        'js' => String | Array<String>,
    
        // Список зависимостей
        // Необходимо указать имена расширений, которые должны быть
        // подключены перед подключением текущего расширения
        // Зависимости подключаются рекурсивно и с учетом указанного порядка
        'rel' => String | Array<String>,
    
        // Путь к файлу с языковыми фразами или массив путей.
        // Файл `lang//config.php` подключается автоматически,
        // здесь его можно не указывать
        'lang' => String | Array<String>,
    
        // Запрещает подключать `main.core` автоматически как зависимость.
        // По умолчанию `false` — `main.core` подключается.
        // При сборке бандла значение параметра устанавливается автоматически,
        // если в коде нет прямой зависимости на `main.core`
        'skip_core' => Boolean,
    
        // Обработчик, который вызывается перед подключением расширения на странице.
        // В качестве первого параметра будет передан массив конфигурации расширения.
        // Обработчик может модифицировать этот массив и вернуть из функции.
        // Это полезно, когда необходимо добавить в языковые фразы
        // какие-то данные с сервера
        'oninit' => Function,
    
        // Дополнительные языковые фразы.
        // Это полезно для передачи вычисляемых значений языковых фраз.
        // Принимает массив. В качестве ключей необходимо указывать идентификаторы языковых фраз
        'lang_additional' => Array<string, string>,
        // Параметр доступен с версии 20.5.100 модуля main.
        // Параметр позволяет указать настройки,
        // которые могут быть получены в JS
        // с помощью метода Extension.getSettings().
        'settings' => Array
    ];
    

Директория @types

Директория может содержать файлы <name>.d.ts с описанием публичного JS API расширения на TypeScript. Рекомендуем использовать файлы *.d.ts для описания API библиотек, написанных на ES5. Описывать код ES6 не нужно.

Пример описания расширения main.loader.

declare module 'main.loader'
{
    type loaderOptions = {
        target?: HTMLElement,
        size?: number,
        mode?: 'absolute' | 'inline' | 'custom',
        offset?: {
            top?: string,
            left?: string
        },
        color?: string
    };

    class Loader
    {
        constructor(options?: loaderOptions);
        readonly layout: HTMLElement;
        readonly circle: HTMLElement;
        createLayout(): HTMLElement;
        show(target?: HTMLElement): Promise<any>;
        hide(): Promise<any>;
        isShown(): boolean;
        setOptions(options: loaderOptions): void;
        destroy(): void;
    }
}

Директория test

Директория должна содержать вложенные директории и файлы Mocha-тестов. Для каждого файла необходимо создать директорию с именем тестируемого файла и файлом с тестами в формате <sourceName>.test.js.

Если структура src имеет вид:

src/
├── entity/
│   ├── column.js
│   └── row.js
└── app.js

Директория test должна иметь следующую структуру:

test/
├── entity/
│   ├── column/
│   │   └── column.test.js
│   └── row/
│       └── row.test.js
└── app/
    └── app.test.js

Использование расширений

В PHP загрузите и подключите расширение на странице с помощью метода\Bitrix\Main\UI\Extension::load. Этот метод принимает в качестве параметра имя расширения либо массив имен.

\Bitrix\Main\UI\Extension::load('main.loader');

В JS можно импортировать экспорты расширения или выполнить отложенное подключение.

  • Импорт экспортов расширения.

    import {Loader} from 'main.loader';
    

    Если вы хотите импортировать старое расширение, которое не поддерживает import ES6, укажите импорт без экспорта расширения.

    import "main.date";
    

    При импорте расширения в JS сборщик автоматически добавляет это расширение как зависимость в config.php.

  • Отложенное подключение.

    import {Runtime} from 'main.core';
    Runtime.loadExtension('main.loader').then((exports) => {
        // Код, который использует `main.loader`
        // В `exports` будут все экспорты из `main.loader`
    });
    

    Отложенная загрузка полезна, когда функционал используется на странице не сразу. Например, когда пользователь откроет всплывающее окно или выполнит какое-нибудь действие.