Подключение фронтенд-библиотек через SIMAI\Main\Page\Asset::load()

В SIMAI Framework 4 фронтенд-библиотеки (lazysizes, swiper, fancybox и т.п.) подключаются не "ручными" addJs/addCss, а через собственный менеджер ассетов SIMAI\Main\Page\Asset.

Конфигурация всех пакетов лежит в /simai.framework/config/.asset.config.php где описаны имена пакетов ('lazysizes', 'jquery', 'simai.framework' и др.), версии, директории и список файлов.

Asset::getInstance()->load("lazysizes") в SIMAI — это не просто "подключить один js-файл", а включить целый преднастроенный пакет из конфигурации фреймворка.

Откуда берётся "lazysizes"

Все подключаемые библиотеки описаны в конфиге simai/config/.asset.config.php. В нём есть блок:


'lazysizes' => array(
    'name' => 'LazySizes',
    'dir'  => '/lazysizes',
    'url'  => 'https://github.com/aFarkas/lazysizes',
    'asset' => array(
        'default' => array(
            'version' => '5.1.0',
            'dir'     => '/lazysizes-5.1.0',
            'file'    => array(
                array('path' => '/lazysizes.min.js',                       'type' => 'script'),
                array('path' => '/plugins/respimg/ls.respimg.min.js',      'type' => 'script'),
                array('path' => '/plugins/unveilhooks/ls.unveilhooks.min.js','type' => 'script'),
            ),
        ),
    ),
),

То есть под ключом "lazysizes" описана группа файлов:

  • ядро lazysizes;
  • плагин respimg;
  • плагин unveilhooks.

И именно весь этот набор вы получаете одной строкой: Asset::getInstance()->load("lazysizes");

Класс SIMAI\Main\Page\Asset: что он делает

Класс располагается в: bitrix/modules/simai.framework/lib/main/page/asset.php

Основные моменты по коду:


namespace SIMAI\Main\Page;

use Bitrix\Main;

class Asset
{
    private static $instance;
    private $storedData = null;
    private $data = array();
    private $isLoaded = false;

    const ASSET_DIR          = SF_DIR . '/asset';
    const ASSET_CONFIG_FILE  = SF_DIR . '/config/.asset.config.php';

Singleton:


public static function getInstance()
{
    if (!isset(self::$instance))
    {
        $c = __CLASS__;
        self::$instance = new $c;
    }

    return self::$instance;
}

То есть вы всегда работаете с одним объектом, накапливающим подключаемые ассеты по всему запросу.

Загрузка конфигурации


private function loadConfiguration()
{
    $this->isLoaded = false;
    $path = static::getPath(self::ASSET_CONFIG_FILE);
    // require .asset.config.php и кладёт результат в $this->data
    ...
    $this->isLoaded = true;
}

При первом вызове любого метода (load, get, add) конфиг читается из simai/config/.asset.config.php и кладётся в $this->data.

Основной метод: load($name, $version = 'default')

Фрагмент:


public function load($name, $version = 'default')
{
    if (!$this->isLoaded)
        $this->loadConfiguration();

    if (isset($this->data[$name]["asset"][$version]) 
        && is_array($this->data[$name]["asset"][$version]['file']))
    {
        $dirAsset  = self::ASSET_DIR.$this->data[$name]['dir'].$this->data[$name]["asset"][$version]['dir'];
        $pathAsset = static::getPath($dirAsset);

        if (!file_exists($pathAsset)) {
            $arVersion = scandir(static::getPath(self::ASSET_DIR.$this->data[$name]['dir']), SCANDIR_SORT_DESCENDING);
            if (!empty($arVersion)) {
                $dirAsset  = self::ASSET_DIR.$this->data[$name]['dir']."/".$arVersion[0];
                $pathAsset = static::getPath($dirAsset);
            }
        }

        foreach($this->data[$name]["asset"][$version]['file'] as $file)
        {
            if (is_file($pathAsset.$file['path']) || $file['type'] == 'string')
            {
                switch ($file['type']) 
                {
                    case 'style':
                        $minFilename = $dirAsset.str_replace(".css",".min.css",$file['path']);
                        if (\COption::GetOptionString("main", "...", "N") == 'Y'
                            && file_exists($_SERVER["DOCUMENT_ROOT"].$minFilename))
                            \Bitrix\Main\Page\Asset::getInstance()->addCss($minFilename);
                        else
                            \Bitrix\Main\Page\Asset::getInstance()->addCss($dirAsset.$file['path']);
                        break;

                    case 'script':
                        $minFilename = $dirAsset.str_replace(".js",".min.js",$file['path']);
                        if (\COption::GetOptionString("main", "...", "N") == 'Y'
                            && file_exists($_SERVER["DOCUMENT_ROOT"].$minFilename))
                            \Bitrix\Main\Page\Asset::getInstance()->addJs($minFilename);
                        else
                            \Bitrix\Main\Page\Asset::getInstance()->addJs($dirAsset.$file['path']);
                        break;

                    case 'string':
                        \Bitrix\Main\Page\Asset::getInstance()->addString($file['path']);
                        break;
                }
            }
        }
    }

    return null;
}

Что важно:

  1. Работа по имени

    Вы указываете только логический ключ ("lazysizes", "jquery", "fancybox" и т.д.), а не путь к файлам.

  2. Версионирование директорий
    • По конфигу берётся директория вида /lazysizes-5.1.0.
    • Если его нет на диске — идёт scandir() по папке /asset/lazysizes/ и берётся последняя версия по имени папки.
  3. Поддержка минифицированных файлов

    Для каждого style/script сначала пробует .min.css / .min.js, и только если включена соответствующая опция в модуле main, и файл реально существует, в Asset добавляется *.min.*. Иначе — обычный.

  4. Тип string

    Позволяет через конфиг добавлять строки в head (мета-теги, инлайновые скрипты) через addString().

По итогу, load() — это "распаковать" логический пакет в набор вызовов стандартного \Bitrix\Main\Page\Asset.

Базовый синтаксис в шаблоне

Типичный пример (его же видно в simai.data/template/style.php):


if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();

\Bitrix\Main\Loader::includeSharewareModule("simai.framework");

use SIMAI\Main\Page\Asset;

// Подключаем нужные пакеты
Asset::getInstance()->load("lazysizes");
Asset::getInstance()->load("jquery");
Asset::getInstance()->load("popper");
Asset::getInstance()->load("simai.framework");
Asset::getInstance()->load("simai.bx-panel");

Минимально необходимое для lazysizes:


\Bitrix\Main\Loader::includeSharewareModule("simai.framework");

use SIMAI\Main\Page\Asset;

Asset::getInstance()->load("lazysizes");

Параметры:

  • $name — ключ из .asset.config.php ("lazysizes", "fancybox", "jquery" и т.д.)
  • $version — опциональный вариант конфигурации (по умолчанию "default"). Если когда-нибудь появятся альтернативные наборы файлов под одним именем, можно будет выбрать нужный.

Чем это лучше прямых addCss/addJs

Преимущества SIMAI\Main\Page\Asset::load() перед ручным Asset-менеджером Битрикса:

  1. Централизованный список библиотек

    Всё в одном файле .asset.config.php. Обновили версию lazysizes → поменяли только папку и номер в конфиге.

  2. Группы файлов вместо россыпи вызовов

    Одна строка load("lazysizes") вместо трёх addJs() с путями к плагинам.

  3. Автоматический выбор минифицированных файлов

    Код сам решает, использовать ли .min.js/.min.css в зависимости от настроек проекта и наличия файлов.

  4. Авто-подхват новой версии по имени папки

    Если описанной версии нет, берётся последняя папка в каталоге библиотеки — удобно при обновлениях.