Подключение фронтенд-библиотек через 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;
}
Что важно:
-
Работа по имени
Вы указываете только логический ключ
("lazysizes", "jquery", "fancybox" и т.д.), а не путь к файлам. - Версионирование директорий
- По конфигу берётся директория вида
/lazysizes-5.1.0. - Если его нет на диске — идёт
scandir()по папке/asset/lazysizes/и берётся последняя версия по имени папки.
- По конфигу берётся директория вида
- Поддержка минифицированных файлов
Для каждого
style/scriptсначала пробует.min.css / .min.js, и только если включена соответствующая опция в модулеmain, и файл реально существует, в Asset добавляется*.min.*. Иначе — обычный. - Тип
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-менеджером Битрикса:
- Централизованный список библиотек
Всё в одном файле
.asset.config.php. Обновили версию lazysizes → поменяли только папку и номер в конфиге. - Группы файлов вместо россыпи вызовов
Одна строка
load("lazysizes")вместо трёхaddJs()с путями к плагинам. - Автоматический выбор минифицированных файлов
Код сам решает, использовать ли
.min.js/.min.cssв зависимости от настроек проекта и наличия файлов. - Авто-подхват новой версии по имени папки
Если описанной версии нет, берётся последняя папка в каталоге библиотеки — удобно при обновлениях.