Как работает Web Asset Manager
В Joomla ресурс проходит два основных состояния: registered и used. После регистрации Web Asset Manager знает о CSS- или JavaScript-файле, но ещё не добавляет его в HTML-документ. Ресурс попадает на страницу только после его активации через useStyle(), useScript(), usePreset() или один из методов registerAndUse*().
Это важное отличие от прямого подключения файлов: описание ресурса и его фактическое использование разделены.
Общая схема выглядит так:
- CSS и JavaScript размещаются в
media-каталоге расширения или шаблона;
- ресурсы описываются в
joomla.asset.json или регистрируются через PHP;
- Web Asset Manager добавляет их в реестр
WebAssetRegistry;
- код расширения активирует нужный ресурс по его имени;
- Joomla определяет зависимости и формирует соответствующие
<link> и <script>.
Главное преимущество Web Asset Manager — код расширения работает не непосредственно с файлами, а с именованными ресурсами. Joomla может учитывать их зависимости, не подключать один и тот же ресурс повторно и правильно определять порядок загрузки.
Как получить WebAssetManager
Web Asset Manager принадлежит текущему объекту документа Joomla. Если код уже работает в контексте документа, например в шаблоне, его можно получить непосредственно:
$wa = $this->getWebAssetManager();
В другом коде расширения документ можно получить через приложение:
use Joomla\CMS\Factory;
$document = Factory::getApplication()->getDocument();
$wa = $document->getWebAssetManager();
Переменная $wa в следующих примерах содержит экземпляр Joomla\CMS\WebAsset\WebAssetManager.
Файл joomla.asset.json
Для расширений с несколькими CSS- и JavaScript-файлами Joomla рекомендует описывать ресурсы декларативно в файле joomla.asset.json. В нём можно указать URI файлов, зависимости, HTML-атрибуты и другие параметры ресурсов.
Для компонента файл обычно размещается здесь:
media/com_example/joomla.asset.json
Например, структура компонента может выглядеть так:
media/com_example/
├── css/
│ └── site.css
├── js/
│ └── site.js
└── joomla.asset.json
Пример joomla.asset.json:
{
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "com_example",
"version": "1.0.0",
"description": "Web assets for com_example",
"license": "GPL-2.0-or-later",
"assets": [
{
"name": "com_example.site",
"type": "style",
"uri": "com_example/site.css"
},
{
"name": "com_example.site",
"type": "script",
"uri": "com_example/site.js",
"dependencies": [
"core"
],
"attributes": {
"defer": true
}
}
]
}
CSS и JavaScript могут иметь одинаковое имя, поскольку это ресурсы разных типов. В примере выше существуют отдельные style и script с именем com_example.site.
Основные поля ресурса
| Поле |
Назначение |
name |
Уникальное имя ресурса в пределах его типа. Именно это имя передаётся в useStyle() или useScript(). |
type |
Тип ресурса: обычно style, script или preset. |
uri |
Путь к CSS- или JavaScript-файлу. |
dependencies |
Имена ресурсов, которые необходимо активировать вместе с текущим ресурсом. |
attributes |
Атрибуты будущего HTML-элемента, например defer, async или type="module". |
Как Joomla определяет путь к CSS и JavaScript
URI ресурса в joomla.asset.json не обязательно совпадает с физическим путём к файлу.
Если JavaScript физически находится здесь:
media/com_example/js/site.js
в определении ресурса используется:
"uri": "com_example/site.js"
Для CSS:
media/com_example/css/site.css
определение будет таким:
"uri": "com_example/site.css"
Web Asset Manager определяет каталог js или css по типу ресурса.
Не копируйте механически пути вроде media/com_example/js/site.js в поле uri. Для ресурсов в стандартной структуре Joomla используется логический URI вроде com_example/site.js.
Подключение зарегистрированных ресурсов
Наличие ресурса в joomla.asset.json ещё не означает, что файл будет загружаться на каждой странице. Его необходимо активировать.
CSS подключается через useStyle():
$wa->useStyle('com_example.site');
JavaScript — через useScript():
$wa->useScript('com_example.site');
Методы поддерживают цепочку вызовов:
$wa
->useStyle('com_example.site')
->useScript('com_example.site');
Таким способом можно загружать ресурсы только в том layout или view, где они действительно нужны.
Наличие ресурса в joomla.asset.json означает его регистрацию, а не автоматическое подключение. Это позволяет одному файлу описывать все ресурсы расширения, не загружая их одновременно.
Зависимости между ресурсами
Поле dependencies описывает другие ресурсы, без которых текущий CSS или JavaScript не может работать.
Например:
{
"name": "com_example.form",
"type": "script",
"uri": "com_example/form.js",
"dependencies": [
"core",
"form.validate"
]
}
После вызова:
$wa->useScript('com_example.form');
Joomla активирует не только com_example.form, но и необходимые ему зависимости. Web Asset Manager также учитывает порядок зависимостей при формировании HTML.
Это позволяет не дублировать в PHP-коде последовательность подключения библиотек.
Не добавляйте зависимость от Joomla-ресурса только на основании предположения. Названия вроде core, jquery или form.validate должны соответствовать реально зарегистрированным ресурсам текущей версии Joomla.
Атрибуты script и link
Через attributes можно передавать атрибуты, которые Joomla добавит к соответствующему HTML-элементу.
Например, JavaScript с defer:
{
"name": "com_example.site",
"type": "script",
"uri": "com_example/site.js",
"attributes": {
"defer": true
}
}
Для JavaScript-модуля можно указать:
{
"name": "com_example.module",
"type": "script",
"uri": "com_example/module.js",
"attributes": {
"type": "module"
}
}
Атрибуты не нужно формировать вручную через HTML — этим занимается Web Asset Manager.
Регистрация ресурсов без joomla.asset.json
Файл joomla.asset.json является рекомендуемым способом описания набора ресурсов расширения, но Web Asset Manager может работать и без него.
CSS можно зарегистрировать непосредственно через PHP:
$wa->registerStyle(
'com_example.custom',
'com_example/custom.css'
);
После этого ресурс активируется отдельно:
$wa->useStyle('com_example.custom');
Или обе операции можно выполнить одним вызовом:
$wa->registerAndUseStyle(
'com_example.custom',
'com_example/custom.css'
);
Аналогичные методы существуют для JavaScript:
$wa->registerAndUseScript(
'com_example.custom',
'com_example/custom.js',
[],
['defer' => true],
['core']
);
Последние два массива задают соответственно HTML-атрибуты и зависимости ресурса.
Когда использовать PHP, а когда joomla.asset.json
Если CSS или JavaScript являются постоянной частью расширения, их лучше описывать в joomla.asset.json. Это отделяет конфигурацию ресурсов от логики PHP и упрощает управление зависимостями.
Программная регистрация полезна, когда ресурс формируется динамически, его URI зависит от условий или необходимо подключить небольшой ресурс только в конкретном контексте.
Когда Joomla автоматически читает joomla.asset.json
Joomla автоматически загружает несколько стандартных реестров ресурсов. Среди них:
media/vendor/joomla.asset.json;
media/system/joomla.asset.json;
media/legacy/joomla.asset.json;
media/{active_component}/joomla.asset.json;
templates/{active_template}/joomla.asset.json.
Это означает, что для активного компонента файл media/com_example/joomla.asset.json обычно попадает в реестр автоматически.
В других случаях, в частности когда собственный joomla.asset.json не входит в стандартную автоматическую загрузку, его можно добавить в реестр вручную:
$registry = $wa->getRegistry();
$registry->addRegistryFile(
'relative/path/to/joomla.asset.json'
);
Не следует исходить из предположения, что Joomla автоматически найдёт любой файл с названием joomla.asset.json. Автоматическая загрузка зависит от типа и контекста расширения.
Preset: группировка CSS и JavaScript
Тип preset позволяет объединить несколько ресурсов и активировать их одним вызовом.
Например:
{
"name": "com_example.bundle",
"type": "preset",
"uri": "",
"dependencies": [
"com_example.site#style",
"com_example.site#script"
]
}
Теперь оба ресурса можно активировать так:
$wa->usePreset('com_example.bundle');
Для зависимостей preset после символа # указывается тип ресурса: #style, #script или другой preset.
Preset удобен, если функциональность состоит из нескольких CSS- и JavaScript-ресурсов, которые почти всегда используются вместе.
Отключение ресурсов
Активированный ресурс можно отключить:
$wa->disableStyle('com_example.site');
$wa->disableScript('com_example.site');
Однако отключение не гарантирует, что ресурс окончательно исчезнет со страницы. Если другой активный ресурс зависит от него, Web Asset Manager может снова активировать эту зависимость.
Поэтому disableScript() и disableStyle() не следует использовать как способ безусловно удалить библиотеку, не проверив граф зависимостей.
Проверка наличия и состояния ресурса
Перед работой с ресурсом можно проверить, зарегистрирован ли он в Web Asset Registry:
if ($wa->assetExists('script', 'com_example.site')) {
$wa->useScript('com_example.site');
}
Чтобы проверить, активирован ли ресурс:
if ($wa->isAssetActive('script', 'com_example.site')) {
// The asset is already active.
}
Эти методы полезны прежде всего в коде, который взаимодействует с ресурсами других расширений или должен работать в разных контекстах.
Как называть собственные ресурсы
Имя ресурса является ключом в Web Asset Registry. Поэтому короткие глобальные названия вроде main, style или script создают ненужный риск конфликтов.
Для собственного компонента лучше использовать пространство имён в названии:
com_example.site
com_example.admin
com_example.form
com_example.product
Для шаблона можно использовать аналогичную схему:
template.mytemplate
template.mytemplate.navigation
Если во время загрузки Joomla встретит новое определение ресурса с тем же именем и типом, предыдущее определение может быть переопределено. Поэтому уникальные и предсказуемые имена особенно важны для сторонних расширений.
Практическая схема для собственного компонента
Для большинства компонентов Joomla 6 достаточно следующей структуры:
media/com_example/
├── css/
│ └── site.css
├── js/
│ └── site.js
└── joomla.asset.json
joomla.asset.json:
{
"$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json",
"name": "com_example",
"version": "1.0.0",
"description": "Assets for com_example",
"license": "GPL-2.0-or-later",
"assets": [
{
"name": "com_example.site",
"type": "style",
"uri": "com_example/site.css"
},
{
"name": "com_example.site",
"type": "script",
"uri": "com_example/site.js",
"dependencies": [
"core"
],
"attributes": {
"defer": true
}
}
]
}
В layout или view, где нужны эти ресурсы:
$wa = $this->getDocument()->getWebAssetManager();
$wa
->useStyle('com_example.site')
->useScript('com_example.site');
В результате конфигурация ресурсов остаётся в joomla.asset.json, а PHP-код лишь сообщает Joomla, какая функциональность нужна на текущей странице.
Типичные ошибки
- ресурс добавлен в
joomla.asset.json, но useStyle() или useScript() нигде не вызывается;
- указан неправильный
uri, например вместе с лишним каталогом js или css;
- в
dependencies используется имя несуществующего ресурса;
- код вызывает
useScript() для ресурса, который ещё не попал в реестр;
- для собственных ресурсов используются слишком общие имена, которые могут конфликтовать с другими расширениями;
- разработчик ожидает, что Joomla автоматически прочитает
joomla.asset.json из произвольного каталога;
- CSS или JavaScript подключается вручную через HTML там, где достаточно Web Asset Manager.
Если useScript() или useStyle() вызывается для незарегистрированного ресурса, Web Asset Manager может сгенерировать UnknownAssetException. При отладке сначала проверьте, был ли загружен файл joomla.asset.json и правильно ли указано имя ресурса.
Что использовать в Joomla 6
Для CSS и JavaScript, которые являются частью расширения, основным подходом следует считать joomla.asset.json в сочетании с useStyle() и useScript(). Это даёт Joomla информацию не только о самом файле, но и о его зависимостях и атрибутах.
Методы registerStyle(), registerScript() и registerAndUse*() остаются полноценной частью API Joomla 6 и подходят для ресурсов, которые целесообразнее определять непосредственно во время выполнения.
Главный принцип прост: сначала ресурс должен быть зарегистрирован, а затем — активирован. Именно на этом построена работа Web Asset Manager.
Использованные источники:
Joomla! Programmers Documentation — Web Asset Manager
Joomla! CMS 6.0 API — WebAssetManager
Joomla! CMS 6.0 API — WebAssetItem
Kevin's Guides — Using Joomla's Web Asset Manager