Создайте пакет UX
Дата обновления перевода 2025-08-26
Создайте пакет UX
Tip
Перед тем как это читать, советуем просмотреть Наилучшие практики для повторно используемых пакетов.
Вот несколько секретов, чтобы сделать так, чтобы ваш пакет устанавливался как пакет UX.
Файл composer.json
Ваш файл composer.json
должен иметь ключевое слово symfony-ux
:
1 2 3
{
"keywords": ["symfony-ux"]
}
Расположение ресурсов
Ваши ресурсы должны быть расположены в одном из следующих каталогов с файлом package.json
, чтобы Flex мог
их обрабатывать во время установки/обновления:
/assets
(рекомендуется)/Resources/assets
/src/Resources/assets
Файл package.json
Ваш файл package.json
должен содержать конфигурацию symfony
с определенными контроллерами,
а также добавить необходимые пакеты в peerDependencies
и importmap
(список
пакетов в importmap
должен быть таким же, как и в peerDependencies
):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
{
"name": "@acme/feature",
"version": "1.0.0",
"symfony": {
"controllers": {
"slug": {
"main": "dist/controller.js",
"fetch": "eager",
"enabled": true,
"autoimport": {
"@acme/feature/dist/bootstrap4-theme.css": false,
"@acme/feature/dist/bootstrap5-theme.css": true
}
}
},
"importmap": {
"@hotwired/stimulus": "^3.0.0",
"slugify": "^1.6.5"
}
},
"peerDependencies": {
"@hotwired/stimulus": "^3.0.0",
"slugify": "^1.6.5"
}
}
В этом случае будет раскрыт файл, расположенный по адресу [assets directory]/dist/controller.js
.
Tip
Вы можете либо написать сырой JS в этом файле dist/controller.js
, либо вы можете, например,
написать свой контроллер с помощью TypeScript и трансполировать его в JavaScript.
Вот пример, как это сделать:
- Добавьте следующее в ваш файл
package.json
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
.. code-block:: json
{
"scripts": {
"build": "babel src --extensions .ts -d dist"
},
"devDependencies": {
"@babel/cli": "^7.20.7",
"@babel/core": "^7.20.12",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.18.6",
"@hotwired/stimulus": "^3.2.1",
"typescript": "^4.9.5"
}
}
Добавьте следующее в ваш файл
babel.config.js
(должно располагаться рядом с вашим файломpackage.json
):1 2 3 4 5 6 7 8 9 10 11 12
module.exports = { presets: [ ['@babel/preset-env', { "loose": true, "modules": false }], ['@babel/preset-typescript', { allowDeclareFields: true }] ], assumptions: { superIsCallableConstructor: false, }, };
- Запустите
npm install
для установки новых зависимостей. - Напишите ваш контроллер Stimulus с помощью TypeScript в файле
src/controller.ts
. - Запустите
npm run build
илиyarn run build
, чтобы трансполировать ваш контроллер TypeScript в JavaScript.
Чтобы использовать ваш контроллер в шаблоне (например, определённом в вашем пакете), вы можете использовать его следующим образом:
1 2 3 4 5 6 7 8 9 10
<div
{{ stimulus_controller('acme/feature/slug', { modal: 'my-value' }) }}
{#
will render:
data-controller="acme--feature--slug"
data-acme--feature--slug-modal-value="my-value"
#}
>
...
</div>
Не забудьте добавить symfony/stimulus-bundle:^2.9
в качестве зависимости композитора для использования
функций Twig stimulus_*
.
Tip
Именование контроллеров: В этом примере name
пакета PHP будет acme/feature
, а имя
контроллера в package.json
- slug
. Следовательно, полное имя контроллера для Stimulus
будет таким: acme--feature--slug
; хотя в функции stimulus_controller()
вы можете использовать
acme/feature/slug
.
Каждый контроллер имеет ряд опций в файле package.json
:
enabled
:- Должен ли быть включен контроллер по умолчанию.
main
:- Путь к файлу контроллера.
fetch
:-
Как включаются контроллеры и зависимости при загрузке страницы.
Используйте
eager
(по умолчанию), чтобы включить контроллер и зависимости в JavaScript, который загружается при загрузке страницы. Используйтеlazy
, чтобы сделать контроллер и зависимости изолированными в отдельном файле и загружать их только асинхронно, если (и когда) на странице появляется HTML контроллер данных. autoimport
:- Список файлов для импорта с контроллером. Полезно, например, когда есть несколько стилей CSS в зависимости от используемого фронтенд-фреймворка (например, Bootstrap 4 или 5, Tailwind CSS...). Значение должно быть объектом с файлами в качестве ключей и булевым значением для каждого файла, чтобы определить, нужно ли импортировать файл.
Специфика Asset Mapper
Чтобы ресурсы вашего пакета работали с AssetMapper, вы должны добавить importmap
в файл package.json
, как указано выше, и добавить некоторые настройки
к контейнеру:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
namespace Acme\FeatureBundle;
use Symfony\Component\AssetMapper\AssetMapperInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class AcmeFeatureBundle extends AbstractBundle
{
public function prependExtension(ContainerConfigurator $configurator, ContainerBuilder $container): void
{
if (!$this->isAssetMapperAvailable($container)) {
return;
}
$container->prependExtensionConfig('framework', [
'asset_mapper' => [
'paths' => [
__DIR__ . '/../assets/dist' => '@acme/feature-bundle',
],
],
]);
}
private function isAssetMapperAvailable(ContainerBuilder $container): bool
{
if (!interface_exists(AssetMapperInterface::class)) {
return false;
}
// проверить, чтобы был установлен FrameworkBundle 6.3 или выше
$bundlesMetadata = $container->getParameter('kernel.bundles_metadata');
if (!isset($bundlesMetadata['FrameworkBundle'])) {
return false;
}
return is_file($bundlesMetadata['FrameworkBundle']['path'] . '/Resources/config/asset_mapper.php');
}
}